test ai-blog

This commit is contained in:
2025-07-15 17:32:20 +09:00
parent 75f108e7b8
commit 0110773592
73 changed files with 9000 additions and 30 deletions

View File

@@ -1274,12 +1274,6 @@ body {
/* Chat Conversation Styles */
.chat-conversation {
margin-bottom: 32px;
padding-bottom: 24px;
border-bottom: 1px solid var(--border);
}
.chat-conversation:last-child {
border-bottom: none;
}
.chat-message.comment-style {

View File

@@ -14,7 +14,7 @@ import OAuthCallback from './components/OAuthCallback.jsx'
export default function App() {
const { user, agent, loading: authLoading, login, logout } = useAuth()
const { adminData, langRecords, commentRecords, loading: dataLoading, error, refresh: refreshAdminData } = useAdminData()
const { adminData, langRecords, commentRecords, chatRecords: adminChatRecords, loading: dataLoading, error, refresh: refreshAdminData } = useAdminData()
const { userComments, chatRecords, loading: userLoading, refresh: refreshUserData } = useUserData(adminData)
const [userChatRecords, setUserChatRecords] = useState([])
const [userChatLoading, setUserChatLoading] = useState(false)
@@ -429,7 +429,7 @@ Answer:`
langRecords={langRecords}
commentRecords={commentRecords}
userComments={userComments}
chatRecords={chatRecords}
chatRecords={adminChatRecords}
userChatRecords={userChatRecords}
userChatLoading={userChatLoading}
baseRecords={adminData.records}

View File

@@ -36,10 +36,56 @@ export default function RecordTabs({ langRecords, commentRecords, userComments,
}
}
// Special filter for chat records (which are already processed into pairs)
const filterChatRecords = (chatPairs) => {
console.log('filterChatRecords called:', {
isTopPage: pageContext.isTopPage,
rkey: pageContext.rkey,
chatPairsLength: chatPairs.length
})
if (pageContext.isTopPage) {
// Top page: show latest 3 pairs
const result = chatPairs.slice(0, 3)
console.log('Top page: returning', result.length, 'pairs')
return result
} else {
// Individual page: show pairs matching the URL (compare path only, ignore domain)
const filtered = chatPairs.filter(chatPair => {
const recordUrl = chatPair.question?.value?.post?.url
if (!recordUrl) {
console.log('No recordUrl for chatPair:', chatPair)
return false
}
try {
// Extract path from URL and get the filename part
const recordPath = new URL(recordUrl).pathname
const recordRkey = recordPath.split('/').pop()?.replace(/\.html$/, '')
console.log('Comparing:', { recordRkey, pageRkey: pageContext.rkey, recordUrl })
// Compare with current page rkey
const matches = recordRkey === pageContext.rkey
if (matches) {
console.log('Found matching chat pair!')
}
return matches
} catch (error) {
console.log('Error processing recordUrl:', recordUrl, error)
return false
}
})
console.log('Individual page: returning', filtered.length, 'filtered pairs')
return filtered
}
}
const filteredLangRecords = filterRecords(langRecords)
const filteredCommentRecords = filterRecords(commentRecords)
const filteredUserComments = filterRecords(userComments || [])
const filteredChatRecords = filterRecords(chatRecords || [])
const filteredChatRecords = filterChatRecords(chatRecords || [])
const filteredBaseRecords = filterRecords(baseRecords || [])
// Filter profile records from baseRecords
@@ -67,7 +113,7 @@ export default function RecordTabs({ langRecords, commentRecords, userComments,
className={`tab-btn ${activeTab === 'collection' ? 'active' : ''}`}
onClick={() => setActiveTab('collection')}
>
chat ({userChatRecords?.length || 0})
chat ({filteredChatRecords.length > 0 ? filteredChatRecords.length : (userChatRecords?.length || 0)})
</button>
<button
className={`tab-btn ${activeTab === 'comment' ? 'active' : ''}`}
@@ -125,7 +171,7 @@ export default function RecordTabs({ langRecords, commentRecords, userComments,
<LoadingSkeleton count={2} showTitle={true} />
) : (
<ChatRecordList
chatPairs={userChatRecords}
chatPairs={filteredChatRecords.length > 0 ? filteredChatRecords : userChatRecords}
apiConfig={apiConfig}
user={user}
agent={agent}

View File

@@ -13,6 +13,7 @@ export function useAdminData() {
})
const [langRecords, setLangRecords] = useState([])
const [commentRecords, setCommentRecords] = useState([])
const [chatRecords, setChatRecords] = useState([])
const [loading, setLoading] = useState(true)
const [error, setError] = useState(null)
@@ -30,15 +31,55 @@ export function useAdminData() {
const profile = await atproto.getProfile(apiConfig.bsky, did)
// Load all data in parallel
const [records, lang, comment] = await Promise.all([
const [records, lang, comment, chat] = await Promise.all([
collections.getBase(apiConfig.pds, did, env.collection),
collections.getLang(apiConfig.pds, did, env.collection),
collections.getComment(apiConfig.pds, did, env.collection)
collections.getComment(apiConfig.pds, did, env.collection),
collections.getChat(apiConfig.pds, did, env.collection)
])
// Process chat records into question-answer pairs
const chatPairs = []
const recordMap = new Map()
// First pass: organize records by base rkey
chat.forEach(record => {
const rkey = record.uri.split('/').pop()
const baseRkey = rkey.replace('-answer', '')
if (!recordMap.has(baseRkey)) {
recordMap.set(baseRkey, { question: null, answer: null })
}
if (record.value.type === 'question') {
recordMap.get(baseRkey).question = record
} else if (record.value.type === 'answer') {
recordMap.get(baseRkey).answer = record
}
})
// Second pass: create chat pairs
recordMap.forEach((pair, rkey) => {
if (pair.question) {
chatPairs.push({
rkey,
question: pair.question,
answer: pair.answer,
createdAt: pair.question.value.createdAt
})
}
})
// Sort by creation time (newest first)
chatPairs.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt))
console.log('useAdminData: raw chat records:', chat.length)
console.log('useAdminData: processed chat pairs:', chatPairs.length, chatPairs)
setAdminData({ did, profile, records, apiConfig })
setLangRecords(lang)
setCommentRecords(comment)
setChatRecords(chatPairs)
} catch (err) {
// Silently fail - no error logging or retry attempts
setError('silent_failure')
@@ -51,6 +92,7 @@ export function useAdminData() {
adminData,
langRecords,
commentRecords,
chatRecords,
loading,
error,
refresh: loadAdminData

View File

@@ -24,13 +24,52 @@ export function useUserData(adminData) {
env.collection
)
// 2. Get chat records from ai.syui.log.chat
// 2. Get chat records from ai.syui.log.chat and process into pairs
const chatRecords = await collections.getChat(
adminData.apiConfig.pds,
adminData.did,
env.collection
)
setChatRecords(chatRecords)
console.log('useUserData: raw chatRecords:', chatRecords.length, chatRecords)
// Process chat records into question-answer pairs
const chatPairs = []
const recordMap = new Map()
// First pass: organize records by base rkey
chatRecords.forEach(record => {
const rkey = record.uri.split('/').pop()
const baseRkey = rkey.replace('-answer', '')
if (!recordMap.has(baseRkey)) {
recordMap.set(baseRkey, { question: null, answer: null })
}
if (record.value.type === 'question') {
recordMap.get(baseRkey).question = record
} else if (record.value.type === 'answer') {
recordMap.get(baseRkey).answer = record
}
})
// Second pass: create chat pairs
recordMap.forEach((pair, rkey) => {
if (pair.question) {
chatPairs.push({
rkey,
question: pair.question,
answer: pair.answer,
createdAt: pair.question.value.createdAt
})
}
})
// Sort by creation time (newest first)
chatPairs.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt))
console.log('useUserData: processed chatPairs:', chatPairs.length, chatPairs)
setChatRecords(chatPairs)
// 3. Get base collection records which contain user comments
const baseRecords = await collections.getBase(

View File

@@ -3,4 +3,8 @@ import ReactDOM from 'react-dom/client'
import App from './App'
import './App.css'
ReactDOM.createRoot(document.getElementById('comment-atproto')).render(<App />)
// Only mount the OAuth app if the target element exists
const targetElement = document.getElementById('comment-atproto')
if (targetElement) {
ReactDOM.createRoot(targetElement).render(<App />)
}