update lexicon site.standard.document
This commit is contained in:
@@ -169,7 +169,6 @@ fn save_chat_local(
|
||||
output_dir: &str,
|
||||
did: &str,
|
||||
content: &str,
|
||||
author_did: &str,
|
||||
root_uri: Option<&str>,
|
||||
parent_uri: Option<&str>,
|
||||
) -> Result<String> {
|
||||
@@ -177,11 +176,16 @@ fn save_chat_local(
|
||||
let now = chrono::Utc::now().format("%Y-%m-%dT%H:%M:%S%.3fZ").to_string();
|
||||
let uri = format!("at://{}/ai.syui.log.chat/{}", did, rkey);
|
||||
|
||||
let site = std::env::var("SITE_URL").unwrap_or_else(|_| "https://syui.ai".to_string());
|
||||
let mut value = serde_json::json!({
|
||||
"$type": "ai.syui.log.chat",
|
||||
"content": content,
|
||||
"author": author_did,
|
||||
"createdAt": now,
|
||||
"site": site,
|
||||
"title": "",
|
||||
"content": {
|
||||
"$type": "ai.syui.log.chat#markdown",
|
||||
"text": content,
|
||||
},
|
||||
"publishedAt": now,
|
||||
});
|
||||
|
||||
if let Some(root) = root_uri {
|
||||
@@ -246,7 +250,6 @@ async fn process_message(
|
||||
output_dir,
|
||||
user_did,
|
||||
input,
|
||||
user_did,
|
||||
session.root_uri.as_deref(),
|
||||
session.last_uri.as_deref(),
|
||||
)?;
|
||||
@@ -270,7 +273,6 @@ async fn process_message(
|
||||
output_dir,
|
||||
bot_did,
|
||||
&response,
|
||||
bot_did,
|
||||
session.root_uri.as_deref(),
|
||||
Some(&user_uri),
|
||||
)?;
|
||||
|
||||
@@ -152,7 +152,6 @@ fn save_chat_record(
|
||||
output_dir: &str,
|
||||
did: &str,
|
||||
content: &str,
|
||||
author_did: &str,
|
||||
root_uri: Option<&str>,
|
||||
parent_uri: Option<&str>,
|
||||
translations: Option<&std::collections::HashMap<String, Translation>>,
|
||||
@@ -161,11 +160,16 @@ fn save_chat_record(
|
||||
let now = chrono::Utc::now().format("%Y-%m-%dT%H:%M:%S%.3fZ").to_string();
|
||||
let uri = format!("at://{}/ai.syui.log.chat/{}", did, rkey);
|
||||
|
||||
let site = std::env::var("SITE_URL").unwrap_or_else(|_| "https://syui.ai".to_string());
|
||||
let mut value = json!({
|
||||
"$type": "ai.syui.log.chat",
|
||||
"content": content,
|
||||
"author": author_did,
|
||||
"createdAt": now,
|
||||
"site": site,
|
||||
"title": "",
|
||||
"content": {
|
||||
"$type": "ai.syui.log.chat#markdown",
|
||||
"text": content,
|
||||
},
|
||||
"publishedAt": now,
|
||||
});
|
||||
|
||||
if let Some(root) = root_uri {
|
||||
@@ -248,7 +252,6 @@ fn handle_chat_save(params: ChatSaveParams) -> Result<String> {
|
||||
&output_dir,
|
||||
&user_did,
|
||||
¶ms.user_message,
|
||||
&user_did,
|
||||
session.root_uri.as_deref(),
|
||||
session.last_uri.as_deref(),
|
||||
params.user_translations.as_ref(),
|
||||
@@ -264,7 +267,6 @@ fn handle_chat_save(params: ChatSaveParams) -> Result<String> {
|
||||
&output_dir,
|
||||
&bot_did,
|
||||
¶ms.bot_response,
|
||||
&bot_did,
|
||||
session.root_uri.as_deref(),
|
||||
Some(&user_uri),
|
||||
params.bot_translations.as_ref(),
|
||||
@@ -307,8 +309,10 @@ fn handle_chat_list() -> Result<String> {
|
||||
let file_path = collection_dir.join(format!("{}.json", rkey));
|
||||
if let Ok(content) = fs::read_to_string(&file_path) {
|
||||
if let Ok(record) = serde_json::from_str::<Value>(&content) {
|
||||
if let Some(msg) = record["value"]["content"].as_str() {
|
||||
messages.push(format!("- {}", msg));
|
||||
let msg = record["value"]["content"]["text"].as_str()
|
||||
.or_else(|| record["value"]["content"].as_str());
|
||||
if let Some(text) = msg {
|
||||
messages.push(format!("- {}", text));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,13 +5,13 @@ import { getCurrentLang } from './mode-tabs'
|
||||
// Get translated content for a chat message
|
||||
function getTranslatedContent(msg: ChatMessage): string {
|
||||
const currentLang = getCurrentLang()
|
||||
const originalLang = msg.value.lang || 'ja'
|
||||
const originalLang = msg.value.langs?.[0] || 'ja'
|
||||
const translations = msg.value.translations
|
||||
|
||||
if (translations && currentLang !== originalLang && translations[currentLang]) {
|
||||
return translations[currentLang].content || msg.value.content
|
||||
return translations[currentLang].content || msg.value.content.text
|
||||
}
|
||||
return msg.value.content
|
||||
return msg.value.content.text
|
||||
}
|
||||
|
||||
// Escape HTML to prevent XSS
|
||||
@@ -36,6 +36,11 @@ function getRkeyFromUri(uri: string): string {
|
||||
return uri.split('/').pop() || ''
|
||||
}
|
||||
|
||||
// Extract DID from AT URI (at://did:plc:xxx/collection/rkey → did:plc:xxx)
|
||||
function getDidFromUri(uri: string): string {
|
||||
return uri.replace('at://', '').split('/')[0]
|
||||
}
|
||||
|
||||
// Profile info for authors
|
||||
interface AuthorInfo {
|
||||
did: string
|
||||
@@ -96,7 +101,7 @@ export function renderChatThreadList(
|
||||
const rootMessages: ChatMessage[] = []
|
||||
|
||||
for (const msg of messages) {
|
||||
if (msg.value.author !== userDid) continue
|
||||
if (getDidFromUri(msg.uri) !== userDid) continue
|
||||
|
||||
if (!msg.value.root) {
|
||||
// No root = explicit conversation start
|
||||
@@ -104,7 +109,7 @@ export function renderChatThreadList(
|
||||
} else if (!allUris.has(msg.value.root)) {
|
||||
// Orphaned root - keep only the oldest message per orphaned root
|
||||
const existing = orphanedRootFirstMsg.get(msg.value.root)
|
||||
if (!existing || new Date(msg.value.createdAt) < new Date(existing.value.createdAt)) {
|
||||
if (!existing || new Date(msg.value.publishedAt) < new Date(existing.value.publishedAt)) {
|
||||
orphanedRootFirstMsg.set(msg.value.root, msg)
|
||||
}
|
||||
}
|
||||
@@ -121,14 +126,14 @@ export function renderChatThreadList(
|
||||
|
||||
const authors = buildAuthorMap(userDid, userHandle, botDid, botHandle, userProfile, botProfile, pds)
|
||||
|
||||
// Sort by createdAt (newest first)
|
||||
// Sort by publishedAt (newest first)
|
||||
const sorted = [...rootMessages].sort((a, b) =>
|
||||
new Date(b.value.createdAt).getTime() - new Date(a.value.createdAt).getTime()
|
||||
new Date(b.value.publishedAt).getTime() - new Date(a.value.publishedAt).getTime()
|
||||
)
|
||||
|
||||
const items = sorted.map(msg => {
|
||||
const authorDid = msg.value.author
|
||||
const time = formatChatTime(msg.value.createdAt)
|
||||
const authorDid = getDidFromUri(msg.uri)
|
||||
const time = formatChatTime(msg.value.publishedAt)
|
||||
const rkey = getRkeyFromUri(msg.uri)
|
||||
const author = authors.get(authorDid) || { did: authorDid, handle: authorDid.slice(0, 20) + '...' }
|
||||
|
||||
@@ -206,14 +211,14 @@ export function renderChatThread(
|
||||
|
||||
const authors = buildAuthorMap(userDid, userHandle, botDid, botHandle, userProfile, botProfile, pds)
|
||||
|
||||
// Sort by createdAt
|
||||
// Sort by publishedAt
|
||||
const sorted = [...threadMessages].sort((a, b) =>
|
||||
new Date(a.value.createdAt).getTime() - new Date(b.value.createdAt).getTime()
|
||||
new Date(a.value.publishedAt).getTime() - new Date(b.value.publishedAt).getTime()
|
||||
)
|
||||
|
||||
const items = sorted.map(msg => {
|
||||
const authorDid = msg.value.author
|
||||
const time = formatChatTime(msg.value.createdAt)
|
||||
const authorDid = getDidFromUri(msg.uri)
|
||||
const time = formatChatTime(msg.value.publishedAt)
|
||||
const rkey = getRkeyFromUri(msg.uri)
|
||||
const author = authors.get(authorDid) || { did: authorDid, handle: authorDid.slice(0, 20) + '...' }
|
||||
|
||||
@@ -287,7 +292,7 @@ export function renderChatEditForm(
|
||||
userHandle: string
|
||||
): string {
|
||||
const rkey = message.uri.split('/').pop() || ''
|
||||
const content = message.value.content
|
||||
const content = message.value.content.text
|
||||
|
||||
return `
|
||||
<div class="chat-edit-container">
|
||||
|
||||
@@ -22,8 +22,8 @@ export function renderPostList(posts: Post[], handle: string): string {
|
||||
|
||||
const items = posts.map(post => {
|
||||
const rkey = post.uri.split('/').pop() || ''
|
||||
const date = formatDate(post.value.createdAt)
|
||||
const originalLang = post.value.lang || 'ja'
|
||||
const date = formatDate(post.value.publishedAt)
|
||||
const originalLang = post.value.langs?.[0] || 'ja'
|
||||
const translations = post.value.translations
|
||||
|
||||
// Use translation if available
|
||||
@@ -55,7 +55,7 @@ export function renderPostDetail(
|
||||
appUrl: string = 'https://bsky.app'
|
||||
): string {
|
||||
const rkey = post.uri.split('/').pop() || ''
|
||||
const date = formatDate(post.value.createdAt)
|
||||
const date = formatDate(post.value.publishedAt)
|
||||
const jsonUrl = `/@${handle}/at/collection/${collection}/${rkey}`
|
||||
|
||||
// Build post URL for discussion search
|
||||
@@ -66,10 +66,10 @@ export function renderPostDetail(
|
||||
// Get current language and show appropriate content
|
||||
const currentLang = getCurrentLang()
|
||||
const translations = post.value.translations
|
||||
const originalLang = post.value.lang || 'ja'
|
||||
const originalLang = post.value.langs?.[0] || 'ja'
|
||||
|
||||
let displayTitle = post.value.title
|
||||
let displayContent = post.value.content
|
||||
let displayContent = post.value.content.text
|
||||
|
||||
// Use translation if available and not original language
|
||||
if (translations && currentLang !== originalLang && translations[currentLang]) {
|
||||
@@ -83,7 +83,7 @@ export function renderPostDetail(
|
||||
const editForm = isOwner ? `
|
||||
<div class="post-edit-form" id="post-edit-form" style="display: none;">
|
||||
<input type="text" class="post-edit-title" id="post-edit-title" value="${escapeHtml(post.value.title)}" placeholder="Title">
|
||||
<textarea class="post-edit-content" id="post-edit-content" rows="15">${escapeHtml(post.value.content)}</textarea>
|
||||
<textarea class="post-edit-content" id="post-edit-content" rows="15">${escapeHtml(post.value.content.text)}</textarea>
|
||||
<div class="post-edit-actions">
|
||||
<button type="button" class="post-edit-cancel" id="post-edit-cancel">Cancel</button>
|
||||
<button type="button" class="post-edit-save" id="post-edit-save" data-collection="${collection}" data-rkey="${rkey}">Save</button>
|
||||
|
||||
@@ -154,7 +154,7 @@ async function getLocalPosts(did: string, collection: string): Promise<Post[]> {
|
||||
if (res.ok && isJsonResponse(res)) posts.push(await res.json())
|
||||
}
|
||||
return posts.sort((a, b) =>
|
||||
new Date(b.value.createdAt).getTime() - new Date(a.value.createdAt).getTime()
|
||||
new Date(b.value.publishedAt).getTime() - new Date(a.value.publishedAt).getTime()
|
||||
)
|
||||
}
|
||||
} catch {
|
||||
@@ -183,7 +183,7 @@ export async function getPosts(did: string, collection: string, localOnly = fals
|
||||
if (res.ok) {
|
||||
const data: ListRecordsResponse<Post> = await res.json()
|
||||
return data.records.sort((a, b) =>
|
||||
new Date(b.value.createdAt).getTime() - new Date(a.value.createdAt).getTime()
|
||||
new Date(b.value.publishedAt).getTime() - new Date(a.value.publishedAt).getTime()
|
||||
)
|
||||
}
|
||||
} catch {
|
||||
@@ -436,9 +436,9 @@ export async function getChatMessages(
|
||||
|
||||
const messages = [...userMessages, ...botMessages]
|
||||
|
||||
// Sort by createdAt
|
||||
// Sort by publishedAt
|
||||
return messages.sort((a, b) =>
|
||||
new Date(a.value.createdAt).getTime() - new Date(b.value.createdAt).getTime()
|
||||
new Date(a.value.publishedAt).getTime() - new Date(b.value.publishedAt).getTime()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -239,9 +239,13 @@ export async function createPost(
|
||||
collection,
|
||||
record: {
|
||||
$type: collection,
|
||||
site: window.location.origin,
|
||||
title,
|
||||
content,
|
||||
createdAt: new Date().toISOString(),
|
||||
content: {
|
||||
$type: `${collection}#markdown`,
|
||||
text: content,
|
||||
},
|
||||
publishedAt: new Date().toISOString(),
|
||||
},
|
||||
})
|
||||
|
||||
@@ -264,7 +268,7 @@ export async function updatePost(
|
||||
try {
|
||||
// Fetch existing record to preserve translations
|
||||
let existingTranslations: unknown = undefined
|
||||
let existingCreatedAt: unknown = new Date().toISOString()
|
||||
let existingPublishedAt: unknown = new Date().toISOString()
|
||||
try {
|
||||
const existing = await agent.com.atproto.repo.getRecord({
|
||||
repo: agent.assertDid,
|
||||
@@ -274,8 +278,8 @@ export async function updatePost(
|
||||
if (existing.data.value) {
|
||||
const value = existing.data.value as Record<string, unknown>
|
||||
existingTranslations = value.translations
|
||||
if (value.createdAt) {
|
||||
existingCreatedAt = value.createdAt
|
||||
if (value.publishedAt) {
|
||||
existingPublishedAt = value.publishedAt
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
@@ -284,9 +288,13 @@ export async function updatePost(
|
||||
|
||||
const record: Record<string, unknown> = {
|
||||
$type: collection,
|
||||
site: window.location.origin,
|
||||
title,
|
||||
content,
|
||||
createdAt: existingCreatedAt,
|
||||
content: {
|
||||
$type: `${collection}#markdown`,
|
||||
text: content,
|
||||
},
|
||||
publishedAt: existingPublishedAt,
|
||||
}
|
||||
|
||||
if (existingTranslations) {
|
||||
|
||||
@@ -165,7 +165,7 @@ async function render(route: Route): Promise<void> {
|
||||
const availableLangs = new Set<string>()
|
||||
for (const post of posts) {
|
||||
// Add original language (default: ja for Japanese posts)
|
||||
const postLang = post.value.lang || 'ja'
|
||||
const postLang = post.value.langs?.[0] || 'ja'
|
||||
availableLangs.add(postLang)
|
||||
// Add translation languages
|
||||
if (post.value.translations) {
|
||||
@@ -302,7 +302,7 @@ async function render(route: Route): Promise<void> {
|
||||
// Collect available languages from chat messages
|
||||
const chatLangs = new Set<string>()
|
||||
for (const msg of chatMessages) {
|
||||
const msgLang = msg.value.lang || 'ja'
|
||||
const msgLang = msg.value.langs?.[0] || 'ja'
|
||||
chatLangs.add(msgLang)
|
||||
if (msg.value.translations) {
|
||||
for (const lang of Object.keys(msg.value.translations)) {
|
||||
@@ -337,7 +337,7 @@ async function render(route: Route): Promise<void> {
|
||||
// Collect available languages from chat messages
|
||||
const chatLangs = new Set<string>()
|
||||
for (const msg of chatMessages) {
|
||||
const msgLang = msg.value.lang || 'ja'
|
||||
const msgLang = msg.value.langs?.[0] || 'ja'
|
||||
chatLangs.add(msgLang)
|
||||
if (msg.value.translations) {
|
||||
for (const lang of Object.keys(msg.value.translations)) {
|
||||
|
||||
@@ -52,15 +52,27 @@ export interface Profile {
|
||||
}
|
||||
}
|
||||
|
||||
export interface ContentMarkdown {
|
||||
$type: string
|
||||
text: string
|
||||
}
|
||||
|
||||
export interface Post {
|
||||
cid: string
|
||||
uri: string
|
||||
value: {
|
||||
$type: string
|
||||
site: string
|
||||
title: string
|
||||
content: string
|
||||
createdAt: string
|
||||
lang?: string
|
||||
content: ContentMarkdown
|
||||
publishedAt: string
|
||||
description?: string
|
||||
updatedAt?: string
|
||||
tags?: string[]
|
||||
path?: string
|
||||
root?: string
|
||||
parent?: string
|
||||
langs?: string[]
|
||||
translations?: {
|
||||
[lang: string]: {
|
||||
title: string
|
||||
@@ -80,12 +92,17 @@ export interface ChatMessage {
|
||||
uri: string
|
||||
value: {
|
||||
$type: string
|
||||
content: string
|
||||
author: string
|
||||
createdAt: string
|
||||
site: string
|
||||
title: string
|
||||
content: ContentMarkdown
|
||||
publishedAt: string
|
||||
description?: string
|
||||
updatedAt?: string
|
||||
tags?: string[]
|
||||
path?: string
|
||||
root?: string
|
||||
parent?: string
|
||||
lang?: string
|
||||
langs?: string[]
|
||||
translations?: {
|
||||
[lang: string]: {
|
||||
content: string
|
||||
|
||||
Reference in New Issue
Block a user