diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 6654e42..b570fb0 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -34,7 +34,8 @@ "Bash(./run.zsh:*)", "Bash(npm run dev:*)", "Bash(./target/release/ailog:*)", - "Bash(rg:*)" + "Bash(rg:*)", + "Bash(../target/release/ailog build)" ], "deny": [] } diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md deleted file mode 100644 index 04073f6..0000000 --- a/DEPLOYMENT.md +++ /dev/null @@ -1,150 +0,0 @@ -# ai.log Deployment Guide - -## 🌐 Cloudflare Tunnel Setup - -ATProto OAuth requires HTTPS for proper CORS handling. Use Cloudflare Tunnel for secure deployment. - -### Prerequisites - -1. **Install cloudflared**: - ```bash - brew install cloudflared - ``` - -2. **Login and create tunnel** (if not already done): - ```bash - cloudflared tunnel login - cloudflared tunnel create ailog - ``` - -3. **Configure DNS**: - - Add a CNAME record: `log.syui.ai` → `[tunnel-id].cfargotunnel.com` - -### Configuration Files - -#### `cloudflared-config.yml` -```yaml -tunnel: a6813327-f880-485d-a9d1-376e6e3df8ad -credentials-file: /Users/syui/.cloudflared/a6813327-f880-485d-a9d1-376e6e3df8ad.json - -ingress: - - hostname: log.syui.ai - service: http://localhost:8080 - originRequest: - noHappyEyeballs: true - - service: http_status:404 -``` - -#### Production Client Metadata -`static/client-metadata-prod.json`: -```json -{ - "client_id": "https://log.syui.ai/client-metadata.json", - "client_name": "ai.log Blog Comment System", - "client_uri": "https://log.syui.ai", - "redirect_uris": ["https://log.syui.ai/"], - "grant_types": ["authorization_code"], - "response_types": ["code"], - "token_endpoint_auth_method": "none", - "application_type": "web" -} -``` - -### Deployment Commands - -#### Quick Start -```bash -# All-in-one deployment -./scripts/tunnel.sh -``` - -#### Manual Steps -```bash -# 1. Build for production -PRODUCTION=true cargo run -- build - -# 2. Start local server -cargo run -- serve --port 8080 & - -# 3. Start tunnel -cloudflared tunnel --config cloudflared-config.yml run -``` - -### Environment Detection - -The system automatically detects environment: - -- **Development** (`localhost:8080`): Uses local client-metadata.json -- **Production** (`log.syui.ai`): Uses HTTPS client-metadata.json - -### CORS Resolution - -✅ **With Cloudflare Tunnel**: -- HTTPS domain: `https://log.syui.ai` -- Valid SSL certificate -- Proper CORS headers -- ATProto OAuth works correctly - -❌ **With localhost**: -- HTTP only: `http://localhost:8080` -- CORS restrictions -- ATProto OAuth may fail - -### Troubleshooting - -#### ATProto OAuth Errors -```javascript -// Check client metadata URL in browser console -console.log('Environment:', window.location.hostname); -console.log('Client ID:', clientId); -``` - -#### Tunnel Connection Issues -```bash -# Check tunnel status -cloudflared tunnel info ailog - -# Test local server -curl http://localhost:8080/client-metadata.json -``` - -#### DNS Propagation -```bash -# Check DNS resolution -dig log.syui.ai -nslookup log.syui.ai -``` - -### Security Notes - -- **Client metadata** is publicly accessible (required by ATProto) -- **Credentials file** contains tunnel secrets (keep secure) -- **HTTPS only** for production OAuth -- **Domain validation** by ATProto servers - -### Integration with ai.ai Ecosystem - -This deployment enables: -- **ai.log**: Comment system with ATProto authentication -- **ai.card**: Shared OAuth widget -- **ai.gpt**: Memory synchronization via ATProto -- **ai.verse**: Future 3D world integration - -### Monitoring - -```bash -# Monitor tunnel logs -cloudflared tunnel --config cloudflared-config.yml run --loglevel debug - -# Monitor blog server -tail -f /path/to/blog/logs - -# Check ATProto connectivity -curl -I https://log.syui.ai/client-metadata.json -``` - ---- - -**🔗 Live URL**: https://log.syui.ai -**📊 Status**: Production Ready -**🌐 ATProto**: OAuth Enabled \ No newline at end of file diff --git a/OAUTH_INTEGRATION_CHANGES.md b/OAUTH_INTEGRATION_CHANGES.md deleted file mode 100644 index a582219..0000000 --- a/OAUTH_INTEGRATION_CHANGES.md +++ /dev/null @@ -1,205 +0,0 @@ -# OAuth Integration Changes for ai.log - -## 概要 -ailogブログシステムにATProto/Bluesky OAuth認証を使用したコメントシステムを統合しました。 - -## 実装された機能 - -### 1. OAuth認証システム -- **ATProto BrowserOAuthClient** を使用した完全なOAuth 2.1フロー -- Blueskyアカウントでのワンクリック認証 -- セッション永続化とリフレッシュトークン対応 - -### 2. コメントシステム -- 認証済みユーザーによるコメント投稿 -- ATProto collection (`ai.syui.log`) への直接保存 -- リアルタイムコメント表示と削除機能 -- 複数PDS対応のコメント取得 - -### 3. 管理機能 -- 管理者用ユーザーリスト管理 -- DID解決とプロフィール情報の自動取得 -- JSON形式でのレコード表示・編集 - -## 技術的変更点 - -### aicard-web-oauth (React OAuth App) - -#### 新規ファイル -``` -aicard-web-oauth/ -├── src/ -│ ├── services/ -│ │ ├── atproto-oauth.ts # BrowserOAuthClient wrapper -│ │ └── auth.ts # Legacy auth service -│ ├── components/ -│ │ ├── OAuthCallback.tsx # OAuth callback handler -│ │ └── OAuthCallbackPage.tsx -│ └── utils/ -│ ├── oauth-endpoints.ts # OAuth endpoint utilities -│ └── oauth-keys.ts # OAuth configuration -``` - -#### 主要な変更 -- **App.tsx**: URL parameter/hash detection, 詳細デバッグログ追加 -- **vite.config.ts**: 固定ファイル名出力 (`comment-atproto.js/css`) -- **main.tsx**: React mount点を `comment-atproto` に変更 - -#### OAuthCallback.tsx の機能 -- Query parameters と hash parameters の両方を検出 -- 認証完了後の自動URL cleanup (`window.history.replaceState`) -- Popup/direct navigation 両対応 -- Fallback認証とエラーハンドリング - -### ailog (Rust Static Site Generator) - -#### OAuth Callback Route -**src/commands/serve.rs**: -```rust -} else if path.starts_with("/oauth/callback") { - // Handle OAuth callback - serve the callback HTML page - match serve_oauth_callback().await { - Ok((ct, data, cc)) => ("200 OK", ct, data, cc), - Err(e) => // Error handling - } -} -``` - -#### OAuth Callback HTML -- ATProto認証パラメータの検出・処理 -- Hash parameters でのリダイレクト (`#code=...&state=...`) -- Popup/window間通信対応 -- localStorage を使った一時的なデータ保存 - -### Template Integration - -#### base.html (ailog templates) -```html - - - -``` - -#### index.html / post.html -```html - -
-``` - -### OAuth Configuration - -#### client-metadata.json -```json -{ - "client_id": "https://log.syui.ai/client-metadata.json", - "redirect_uris": [ - "https://log.syui.ai/oauth/callback", - "https://log.syui.ai/" - ], - "scope": "atproto transition:generic", - "dpop_bound_access_tokens": true -} -``` - -## インフラストラクチャ - -### Cloudflare Tunnel -```yaml -# cloudflared-config.yml -ingress: - - hostname: log.syui.ai - service: http://localhost:4173 # ailog serve -``` - -### Build Process -1. **aicard-web-oauth**: `npm run build` → `dist/assets/` -2. **Asset copy**: `dist/assets/*` → `my-blog/public/assets/` -3. **ailog build**: Template processing + static file serving - -## データフロー - -### OAuth認証フロー -``` -1. User clicks "atproto" button -2. BrowserOAuthClient initiates OAuth flow -3. Redirect to Bluesky authorization server -4. Callback to https://log.syui.ai/oauth/callback -5. ailog serves OAuth callback HTML -6. JavaScript processes parameters and redirects with hash -7. React app detects hash parameters and completes authentication -8. URL cleanup removes OAuth parameters -``` - -### コメント投稿フロー -``` -1. Authenticated user writes comment -2. React app calls ATProto API -3. Record saved to ai.syui.log collection -4. Comments reloaded from all configured PDS endpoints -5. Real-time display update -``` - -## 設定ファイル - -### 必須ファイル -- `my-blog/static/client-metadata.json` - OAuth client configuration -- `aicard-web-oauth/.env.production` - Production environment variables -- `cloudflared-config.yml` - Tunnel routing configuration - -### 開発用ファイル -- `aicard-web-oauth/.env.development` - Development settings -- `aicard-web-oauth/public/client-metadata.json` - Local OAuth metadata - -## 主要な修正点 - -### 1. Build System -- Vite output ファイル名を固定 (`comment-atproto.js/css`) -- Build時のclient-metadata.json更新自動化 - -### 2. OAuth Callback処理 -- Hash parameters 対応でSPA architectureに最適化 -- URL cleanup でクリーンなユーザー体験 -- Popup/direct navigation 両対応 - -### 3. Error Handling -- Network エラー時のfallback認証 -- セッション期限切れ時の再認証 -- OAuth parameter不足時の適切なエラー表示 - -### 4. Session Management -- localStorage + sessionStorage 併用 -- OAuth state/code verifier の適切な管理 -- Cross-tab session sharing - -## テスト済み機能 - -✅ **動作確認済み** -- OAuth認証 (Bluesky) -- コメント投稿・削除 -- セッション永続化 -- URL parameter cleanup -- 複数PDS対応 -- 管理者機能 - -⏳ **今後のテスト項目** -- Incognito/private mode での動作 -- 複数タブでの同時使用 -- Long-term session の動作確認 - -## 運用メモ - -### デプロイ手順 -1. `cd aicard-web-oauth && npm run build` -2. `cp -r dist/assets/* ../my-blog/public/assets/` -3. `cd my-blog && cargo build --release` -4. ailog serve でテスト確認 - -### トラブルシューティング -- OAuth エラー: client-metadata.json のredirect_uris確認 -- コメント表示されない: Network tab でAPI response確認 -- Build エラー: Node.js/npm version, dependencies確認 - -## 関連リンク -- [ATProto OAuth Specification](https://atproto.com/specs/oauth) -- [Bluesky OAuth Documentation](https://github.com/bluesky-social/atproto/blob/main/packages/api/OAUTH.md) -- [BrowserOAuthClient API](https://github.com/bluesky-social/atproto/tree/main/packages/oauth-client-browser) \ No newline at end of file diff --git a/README.md b/README.md index 348caaf..e62ecf7 100644 --- a/README.md +++ b/README.md @@ -22,9 +22,15 @@ highlight_code = true minify = false [ai] -enabled = false +enabled = true auto_translate = false comment_moderation = false +ask_ai = true +provider = "ollama" +model = "gemma3:4b" +host = "https://ollama.yourdomain.com" +system_prompt = "You are a helpful AI assistant trained on this blog's content." +ai_did = "did:plc:your-ai-bot-did" # 3. Build your blog ailog build @@ -125,10 +131,14 @@ ai.logは、[Anthropic Docs](https://docs.anthropic.com/)にインスパイア - **レスポンシブ**: モバイル・デスクトップ対応 ### 🤖 AI統合機能 -- **Ask AI**: ローカルLLM(Ollama)による質問応答 +- **Ask AI**: ローカルLLM(Ollama)による質問応答 ✅ + - トップページでのみ利用可能 + - atproto OAuth認証必須 + - Cloudflare Tunnel経由でCORS問題解決済み - **自動翻訳**: 日本語↔英語の自動生成 - **AI記事強化**: コンテンツの自動改善 - **AIコメント**: 記事への一言コメント生成 +- **カスタマイズ可能なAI設定**: system_prompt、ai_did、プロフィール連携 ### 🌐 分散SNS連携 - **atproto OAuth**: Blueskyアカウントでログイン @@ -341,6 +351,10 @@ Generate comprehensive documentation and translate content: - **💬 ATProto comment system with Jetstream monitoring** - **🔄 Real-time comment collection and user management** - **🔐 OAuth 2.1 integration with Cloudflare tunnel** +- **🤖 Ask AI feature with Ollama integration** +- **⚡ CORS resolution via OLLAMA_ORIGINS** +- **🔒 Authentication-gated AI chat** +- **📱 Top-page-only AI access pattern** - Test blog with sample content and styling ### 🚧 In Progress diff --git a/oauth/.env.production b/oauth/.env.production index d03edc3..4c59f4c 100644 --- a/oauth/.env.production +++ b/oauth/.env.production @@ -7,7 +7,18 @@ VITE_ADMIN_DID=did:plc:uqzpqmrjnptsxezjx4xuh2mn # Collection names for OAuth app VITE_COLLECTION_COMMENT=ai.syui.log VITE_COLLECTION_USER=ai.syui.log.user +VITE_COLLECTION_CHAT=ai.syui.log.chat # Collection names for ailog (backward compatibility) AILOG_COLLECTION_COMMENT=ai.syui.log AILOG_COLLECTION_USER=ai.syui.log.user +AILOG_COLLECTION_CHAT=ai.syui.log.chat + +# AI Configuration +VITE_AI_ENABLED=true +VITE_AI_ASK_AI=true +VITE_AI_PROVIDER=ollama +VITE_AI_MODEL=gemma3:4b +VITE_AI_HOST=https://ollama.syui.ai +VITE_AI_SYSTEM_PROMPT="You are a helpful AI assistant trained on this blog's content. You can answer questions about the articles, provide insights, and help users understand the topics discussed." +VITE_AI_DID=did:plc:uqzpqmrjnptsxezjx4xuh2mn diff --git a/oauth/src/App.tsx b/oauth/src/App.tsx index 9246a42..e64f00d 100644 --- a/oauth/src/App.tsx +++ b/oauth/src/App.tsx @@ -1,5 +1,6 @@ import React, { useState, useEffect } from 'react'; import { OAuthCallback } from './components/OAuthCallback'; +import { AIChat } from './components/AIChat'; import { authService, User } from './services/auth'; import { atprotoOAuthService } from './services/atproto-oauth'; import { appConfig } from './config/app'; @@ -83,8 +84,8 @@ function App() { } }; - // Jetstream + Cache example - const jetstream = setupJetstream(); + // Jetstream + Cache example (disabled for now) + // const jetstream = setupJetstream(); // キャッシュからコメント読み込み const loadCachedComments = () => { @@ -102,7 +103,10 @@ function App() { // キャッシュがなければ、ATProtoから取得(認証状態に関係なく) if (!loadCachedComments()) { + console.log('No cached comments found, loading from ATProto...'); loadAllComments(); // URLフィルタリングを無効にして全コメント表示 + } else { + console.log('Cached comments loaded successfully'); } // Handle popstate events for mock OAuth flow @@ -144,6 +148,7 @@ function App() { // Load all comments for display (this will be the default view) // Temporarily disable URL filtering to see all comments + console.log('OAuth session found, loading all comments...'); loadAllComments(); // Load user list records if admin @@ -164,6 +169,7 @@ function App() { // Load all comments for display (this will be the default view) // Temporarily disable URL filtering to see all comments + console.log('Legacy auth session found, loading all comments...'); loadAllComments(); // Load user list records if admin @@ -174,6 +180,7 @@ function App() { setIsLoading(false); // 認証状態に関係なく、コメントを読み込む + console.log('No auth session found, loading all comments anyway...'); loadAllComments(); }; @@ -480,6 +487,7 @@ function App() { console.log('Known users used:', knownUsers); setComments(enhancedComments); + console.log('Comments state updated with', enhancedComments.length, 'comments'); // キャッシュに保存(5分間有効) if (pageUrl) { @@ -1076,6 +1084,8 @@ function App() { + {/* AI Chat Component - handles all AI functionality */} +