fix config
This commit is contained in:
@@ -2,9 +2,15 @@
|
|||||||
"title": "syui.ai",
|
"title": "syui.ai",
|
||||||
"did": "did:plc:vzsvtbtbnwn22xjqhcu3vd6y",
|
"did": "did:plc:vzsvtbtbnwn22xjqhcu3vd6y",
|
||||||
"handle": "syui.syui.ai",
|
"handle": "syui.syui.ai",
|
||||||
|
"bot": {
|
||||||
|
"did": "did:plc:6qyecktefllvenje24fcxnie",
|
||||||
|
"handle": "ai.syui.ai"
|
||||||
|
},
|
||||||
"collection": "ai.syui.log.post",
|
"collection": "ai.syui.log.post",
|
||||||
|
"chatCollection": "ai.syui.log.chat",
|
||||||
"network": "syu.is",
|
"network": "syu.is",
|
||||||
"color": "#EF454A",
|
"color": "#EF454A",
|
||||||
"siteUrl": "https://syui.ai",
|
"siteUrl": "https://syui.ai",
|
||||||
|
"repoUrl": "https://git.syui.ai/ai/log",
|
||||||
"oauth": true
|
"oauth": true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,13 @@
|
|||||||
"bsky.social": {
|
"bsky.social": {
|
||||||
"plc": "https://plc.directory",
|
"plc": "https://plc.directory",
|
||||||
"bsky": "https://public.api.bsky.app",
|
"bsky": "https://public.api.bsky.app",
|
||||||
"web": "https://bsky.app"
|
"web": "https://bsky.app",
|
||||||
|
"handleDomains": ["bsky.social"]
|
||||||
},
|
},
|
||||||
"syu.is": {
|
"syu.is": {
|
||||||
"plc": "https://plc.syu.is",
|
"plc": "https://plc.syu.is",
|
||||||
"bsky": "https://bsky.syu.is",
|
"bsky": "https://bsky.syu.is",
|
||||||
"web": "https://syu.is"
|
"web": "https://syu.is",
|
||||||
|
"handleDomains": ["syu.is", "syui.ai"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -223,14 +223,16 @@ fn handle_chat_save(params: ChatSaveParams) -> Result<String> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Get user DID from token.json
|
// Get user DID from token.json
|
||||||
let user_did = token::load_session()
|
let user_did = match token::load_session() {
|
||||||
.map(|s| s.did)
|
Ok(s) => s.did,
|
||||||
.unwrap_or_else(|_| "did:plc:unknown".to_string());
|
Err(_) => return Err(anyhow::anyhow!("User not logged in. Run: ailog login <handle> -p <password>")),
|
||||||
|
};
|
||||||
|
|
||||||
// Get bot DID from bot.json
|
// Get bot DID from bot.json
|
||||||
let bot_did = token::load_bot_session()
|
let bot_did = match token::load_bot_session() {
|
||||||
.map(|s| s.did)
|
Ok(s) => s.did,
|
||||||
.unwrap_or_else(|_| "did:plc:6qyecktefllvenje24fcxnie".to_string());
|
Err(_) => return Err(anyhow::anyhow!("Bot not logged in. Run: ailog login <handle> -p <password> --bot")),
|
||||||
|
};
|
||||||
|
|
||||||
// Reset session if new_thread requested
|
// Reset session if new_thread requested
|
||||||
if params.new_thread {
|
if params.new_thread {
|
||||||
@@ -278,9 +280,10 @@ fn handle_chat_list() -> Result<String> {
|
|||||||
.to_string()
|
.to_string()
|
||||||
});
|
});
|
||||||
|
|
||||||
let user_did = token::load_session()
|
let user_did = match token::load_session() {
|
||||||
.map(|s| s.did)
|
Ok(s) => s.did,
|
||||||
.unwrap_or_else(|_| "did:plc:unknown".to_string());
|
Err(_) => return Err(anyhow::anyhow!("User not logged in. Run: ailog login <handle> -p <password>")),
|
||||||
|
};
|
||||||
|
|
||||||
let collection_dir = std::path::Path::new(&output_dir)
|
let collection_dir = std::path::Path::new(&output_dir)
|
||||||
.join(&user_did)
|
.join(&user_did)
|
||||||
|
|||||||
@@ -171,10 +171,11 @@ export function renderChatThread(
|
|||||||
botHandle: string,
|
botHandle: string,
|
||||||
userProfile?: Profile | null,
|
userProfile?: Profile | null,
|
||||||
botProfile?: Profile | null,
|
botProfile?: Profile | null,
|
||||||
pds?: string
|
pds?: string,
|
||||||
|
chatCollection: string = 'ai.syui.log.chat'
|
||||||
): string {
|
): string {
|
||||||
// Find root message
|
// Find root message
|
||||||
const rootUri = `at://${userDid}/ai.syui.log.chat/${rootRkey}`
|
const rootUri = `at://${userDid}/${chatCollection}/${rootRkey}`
|
||||||
const rootMsg = messages.find(m => m.uri === rootUri)
|
const rootMsg = messages.find(m => m.uri === rootUri)
|
||||||
|
|
||||||
if (!rootMsg) {
|
if (!rootMsg) {
|
||||||
@@ -222,7 +223,7 @@ export function renderChatThread(
|
|||||||
|
|
||||||
const displayContent = getTranslatedContent(msg)
|
const displayContent = getTranslatedContent(msg)
|
||||||
const content = renderMarkdown(displayContent)
|
const content = renderMarkdown(displayContent)
|
||||||
const recordLink = `/@${author.handle}/at/collection/ai.syui.log.chat/${rkey}`
|
const recordLink = `/@${author.handle}/at/collection/${chatCollection}/${rkey}`
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<article class="chat-message">
|
<article class="chat-message">
|
||||||
@@ -268,8 +269,9 @@ export function renderChatThreadPage(
|
|||||||
botHandle: string,
|
botHandle: string,
|
||||||
userProfile?: Profile | null,
|
userProfile?: Profile | null,
|
||||||
botProfile?: Profile | null,
|
botProfile?: Profile | null,
|
||||||
pds?: string
|
pds?: string,
|
||||||
|
chatCollection: string = 'ai.syui.log.chat'
|
||||||
): string {
|
): string {
|
||||||
const thread = renderChatThread(messages, rootRkey, userDid, userHandle, botDid, botHandle, userProfile, botProfile, pds)
|
const thread = renderChatThread(messages, rootRkey, userDid, userHandle, botDid, botHandle, userProfile, botProfile, pds, chatCollection)
|
||||||
return `<div class="chat-container">${thread}</div>`
|
return `<div class="chat-container">${thread}</div>`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
export function renderFooter(handle: string): string {
|
export function renderFooter(handle: string, repoUrl?: string): string {
|
||||||
// Extract username from handle: {username}.{name}.{domain} -> username
|
// Extract username from handle: {username}.{name}.{domain} -> username
|
||||||
const username = handle.split('.')[0] || handle
|
const username = handle.split('.')[0] || handle
|
||||||
|
const repo = repoUrl || '#'
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<footer id="footer" class="footer">
|
<footer id="footer" class="footer">
|
||||||
<div class="license">
|
<div class="license">
|
||||||
<a href="https://git.syui.ai/ai/log" target="_blank" rel="noopener">
|
<a href="${repo}" target="_blank" rel="noopener">
|
||||||
<img src="/ai.svg" alt="ai" class="license-icon">
|
<img src="/ai.svg" alt="ai" class="license-icon">
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -34,21 +34,21 @@ function filterCollectionsByService(collections: string[], service: string): str
|
|||||||
async function getWebUrl(handle: string): Promise<string | undefined> {
|
async function getWebUrl(handle: string): Promise<string | undefined> {
|
||||||
const networks = await getNetworks()
|
const networks = await getNetworks()
|
||||||
// Check each network for matching handle domain
|
// Check each network for matching handle domain
|
||||||
for (const [domain, network] of Object.entries(networks)) {
|
for (const [_domain, network] of Object.entries(networks)) {
|
||||||
// Direct domain match (e.g., handle.syu.is -> syu.is)
|
// Check handleDomains if configured
|
||||||
if (handle.endsWith(`.${domain}`)) {
|
if (network.handleDomains) {
|
||||||
|
for (const hd of network.handleDomains) {
|
||||||
|
if (handle.endsWith(`.${hd}`)) {
|
||||||
return network.web
|
return network.web
|
||||||
}
|
}
|
||||||
// Check if handle domain matches network's web domain (e.g., syui.syui.ai -> syu.is via web: syu.is)
|
}
|
||||||
|
}
|
||||||
|
// Check if handle domain matches network's web domain
|
||||||
const webDomain = network.web?.replace(/^https?:\/\//, '')
|
const webDomain = network.web?.replace(/^https?:\/\//, '')
|
||||||
if (webDomain && handle.endsWith(`.${webDomain}`)) {
|
if (webDomain && handle.endsWith(`.${webDomain}`)) {
|
||||||
return network.web
|
return network.web
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Check for syui.ai handles -> syu.is network
|
|
||||||
if (handle.endsWith('.syui.ai')) {
|
|
||||||
return networks['syu.is']?.web
|
|
||||||
}
|
|
||||||
// Default to first network's web
|
// Default to first network's web
|
||||||
const firstNetwork = Object.values(networks)[0]
|
const firstNetwork = Object.values(networks)[0]
|
||||||
return firstNetwork?.web
|
return firstNetwork?.web
|
||||||
@@ -127,7 +127,7 @@ async function render(route: Route): Promise<void> {
|
|||||||
app.innerHTML = `
|
app.innerHTML = `
|
||||||
${renderHeader(handle, oauthEnabled)}
|
${renderHeader(handle, oauthEnabled)}
|
||||||
<div class="error">Could not resolve handle: ${handle}</div>
|
<div class="error">Could not resolve handle: ${handle}</div>
|
||||||
${renderFooter(handle)}
|
${renderFooter(handle, config.repoUrl)}
|
||||||
`
|
`
|
||||||
setupEventHandlers()
|
setupEventHandlers()
|
||||||
return
|
return
|
||||||
@@ -230,13 +230,18 @@ async function render(route: Route): Promise<void> {
|
|||||||
|
|
||||||
} else if (route.type === 'chat') {
|
} else if (route.type === 'chat') {
|
||||||
// Chat list page - show threads started by this user
|
// Chat list page - show threads started by this user
|
||||||
const aiDid = 'did:plc:6qyecktefllvenje24fcxnie' // ai.syui.ai
|
if (!config.bot) {
|
||||||
const aiHandle = 'ai.syui.ai'
|
html += `<div id="content" class="error">Bot not configured in config.json</div>`
|
||||||
|
html += `<nav class="back-nav"><a href="/@${handle}">${handle}</a></nav>`
|
||||||
|
} else {
|
||||||
|
const botDid = config.bot.did
|
||||||
|
const botHandle = config.bot.handle
|
||||||
|
const chatCollection = config.chatCollection || 'ai.syui.log.chat'
|
||||||
|
|
||||||
// Load messages and profiles in parallel
|
// Load messages and profiles in parallel
|
||||||
const [chatMessages, aiProfile, pds] = await Promise.all([
|
const [chatMessages, botProfile, pds] = await Promise.all([
|
||||||
getChatMessages(did, aiDid, 'ai.syui.log.chat'),
|
getChatMessages(did, botDid, chatCollection),
|
||||||
getProfile(aiDid, false),
|
getProfile(botDid, false),
|
||||||
getPds(did)
|
getPds(did)
|
||||||
])
|
])
|
||||||
|
|
||||||
@@ -254,18 +259,24 @@ async function render(route: Route): Promise<void> {
|
|||||||
langList = Array.from(chatLangs)
|
langList = Array.from(chatLangs)
|
||||||
|
|
||||||
html += renderLangSelector(langList)
|
html += renderLangSelector(langList)
|
||||||
html += `<div id="content">${renderChatListPage(chatMessages, did, handle, aiDid, aiHandle, profile, aiProfile, pds || undefined)}</div>`
|
html += `<div id="content">${renderChatListPage(chatMessages, did, handle, botDid, botHandle, profile, botProfile, pds || undefined)}</div>`
|
||||||
html += `<nav class="back-nav"><a href="/@${handle}">${handle}</a></nav>`
|
html += `<nav class="back-nav"><a href="/@${handle}">${handle}</a></nav>`
|
||||||
|
}
|
||||||
|
|
||||||
} else if (route.type === 'chat-thread' && route.rkey) {
|
} else if (route.type === 'chat-thread' && route.rkey) {
|
||||||
// Chat thread page - show full conversation
|
// Chat thread page - show full conversation
|
||||||
const aiDid = 'did:plc:6qyecktefllvenje24fcxnie' // ai.syui.ai
|
if (!config.bot) {
|
||||||
const aiHandle = 'ai.syui.ai'
|
html += `<div id="content" class="error">Bot not configured in config.json</div>`
|
||||||
|
html += `<nav class="back-nav"><a href="/@${handle}">${handle}</a></nav>`
|
||||||
|
} else {
|
||||||
|
const botDid = config.bot.did
|
||||||
|
const botHandle = config.bot.handle
|
||||||
|
const chatCollection = config.chatCollection || 'ai.syui.log.chat'
|
||||||
|
|
||||||
// Load messages and profiles in parallel
|
// Load messages and profiles in parallel
|
||||||
const [chatMessages, aiProfile, pds] = await Promise.all([
|
const [chatMessages, botProfile, pds] = await Promise.all([
|
||||||
getChatMessages(did, aiDid, 'ai.syui.log.chat'),
|
getChatMessages(did, botDid, chatCollection),
|
||||||
getProfile(aiDid, false),
|
getProfile(botDid, false),
|
||||||
getPds(did)
|
getPds(did)
|
||||||
])
|
])
|
||||||
|
|
||||||
@@ -283,8 +294,9 @@ async function render(route: Route): Promise<void> {
|
|||||||
langList = Array.from(chatLangs)
|
langList = Array.from(chatLangs)
|
||||||
|
|
||||||
html += renderLangSelector(langList)
|
html += renderLangSelector(langList)
|
||||||
html += `<div id="content">${renderChatThreadPage(chatMessages, route.rkey, did, handle, aiDid, aiHandle, profile, aiProfile, pds || undefined)}</div>`
|
html += `<div id="content">${renderChatThreadPage(chatMessages, route.rkey, did, handle, botDid, botHandle, profile, botProfile, pds || undefined, chatCollection)}</div>`
|
||||||
html += `<nav class="back-nav"><a href="/@${handle}/at/chat">chat</a></nav>`
|
html += `<nav class="back-nav"><a href="/@${handle}/at/chat">chat</a></nav>`
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// User page: compact collection buttons + posts
|
// User page: compact collection buttons + posts
|
||||||
@@ -298,7 +310,7 @@ async function render(route: Route): Promise<void> {
|
|||||||
html += `<div id="content">${renderPostList(posts, handle)}</div>`
|
html += `<div id="content">${renderPostList(posts, handle)}</div>`
|
||||||
}
|
}
|
||||||
|
|
||||||
html += renderFooter(handle)
|
html += renderFooter(handle, config.repoUrl)
|
||||||
|
|
||||||
app.innerHTML = html
|
app.innerHTML = html
|
||||||
hideLoading(app)
|
hideLoading(app)
|
||||||
@@ -349,7 +361,7 @@ async function render(route: Route): Promise<void> {
|
|||||||
app.innerHTML = `
|
app.innerHTML = `
|
||||||
${renderHeader(currentHandle, false)}
|
${renderHeader(currentHandle, false)}
|
||||||
<div class="error">Error: ${error}</div>
|
<div class="error">Error: ${error}</div>
|
||||||
${renderFooter(currentHandle)}
|
${renderFooter(currentHandle, undefined)}
|
||||||
`
|
`
|
||||||
hideLoading(app)
|
hideLoading(app)
|
||||||
setupEventHandlers()
|
setupEventHandlers()
|
||||||
|
|||||||
@@ -1,12 +1,20 @@
|
|||||||
// Config types
|
// Config types
|
||||||
|
export interface BotConfig {
|
||||||
|
did: string
|
||||||
|
handle: string
|
||||||
|
}
|
||||||
|
|
||||||
export interface AppConfig {
|
export interface AppConfig {
|
||||||
title: string
|
title: string
|
||||||
did?: string
|
did?: string
|
||||||
handle: string
|
handle: string
|
||||||
|
bot?: BotConfig
|
||||||
collection: string
|
collection: string
|
||||||
|
chatCollection?: string
|
||||||
network: string
|
network: string
|
||||||
color: string
|
color: string
|
||||||
siteUrl: string
|
siteUrl: string
|
||||||
|
repoUrl?: string
|
||||||
oauth?: boolean
|
oauth?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -15,6 +23,7 @@ export interface Networks {
|
|||||||
plc: string
|
plc: string
|
||||||
bsky: string
|
bsky: string
|
||||||
web: string
|
web: string
|
||||||
|
handleDomains?: string[]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user