This file is a merged representation of the entire codebase, combined into a single document by Repomix. ================================================================ File Summary ================================================================ Purpose: -------- This file contains a packed representation of the entire repository's contents. It is designed to be easily consumable by AI systems for analysis, code review, or other automated processes. File Format: ------------ The content is organized as follows: 1. This summary section 2. Repository information 3. Directory structure 4. Repository files (if enabled) 4. Multiple file entries, each consisting of: a. A separator line (================) b. The file path (File: path/to/file) c. Another separator line d. The full contents of the file e. A blank line Usage Guidelines: ----------------- - This file should be treated as read-only. Any changes should be made to the original repository files, not this packed version. - When processing this file, use the file path to distinguish between different files in the repository. - Be aware that this file may contain sensitive information. Handle it with the same level of security as you would the original repository. Notes: ------ - Some files may have been excluded based on .gitignore rules and Repomix's configuration - Binary files are not included in this packed representation. Please refer to the Repository Structure section for a complete list of file paths, including binary files - Files matching patterns in .gitignore are excluded - Files matching default ignore patterns are excluded - Files are sorted by Git change count (files with more changes are at the bottom) Additional Info: ---------------- ================================================================ Directory Structure ================================================================ public/ file.svg globe.svg next.svg vercel.svg window.svg src/ app/ about/ page.tsx ai-post/ page.tsx components/ background/ text-background.tsx layout/ footer.tsx header.tsx index.ts theme-toggle.tsx contact/ page.tsx contexts/ theme.tsx post/ [slug]/ page.tsx card.tsx markdown-content.tsx page.tsx utils/ post.ts globals.css layout.tsx page.tsx mastra/ agents/ index.ts tools/ index.ts types/ daily-papers.ts workflows/ daily-papers-workflow.ts index.ts weather-workflow.ts index.ts post/ ai-future.md generative-models.md .gitignore next.config.ts package.json postcss.config.mjs README.md tsconfig.json ================================================================ Files ================================================================ ================ File: public/file.svg ================ <svg fill="none" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M14.5 13.5V5.41a1 1 0 0 0-.3-.7L9.8.29A1 1 0 0 0 9.08 0H1.5v13.5A2.5 2.5 0 0 0 4 16h8a2.5 2.5 0 0 0 2.5-2.5m-1.5 0v-7H8v-5H3v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1M9.5 5V2.12L12.38 5zM5.13 5h-.62v1.25h2.12V5zm-.62 3h7.12v1.25H4.5zm.62 3h-.62v1.25h7.12V11z" clip-rule="evenodd" fill="#666" fill-rule="evenodd"/></svg> ================ File: public/globe.svg ================ <svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g clip-path="url(#a)"><path fill-rule="evenodd" clip-rule="evenodd" d="M10.27 14.1a6.5 6.5 0 0 0 3.67-3.45q-1.24.21-2.7.34-.31 1.83-.97 3.1M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16m.48-1.52a7 7 0 0 1-.96 0H7.5a4 4 0 0 1-.84-1.32q-.38-.89-.63-2.08a40 40 0 0 0 3.92 0q-.25 1.2-.63 2.08a4 4 0 0 1-.84 1.31zm2.94-4.76q1.66-.15 2.95-.43a7 7 0 0 0 0-2.58q-1.3-.27-2.95-.43a18 18 0 0 1 0 3.44m-1.27-3.54a17 17 0 0 1 0 3.64 39 39 0 0 1-4.3 0 17 17 0 0 1 0-3.64 39 39 0 0 1 4.3 0m1.1-1.17q1.45.13 2.69.34a6.5 6.5 0 0 0-3.67-3.44q.65 1.26.98 3.1M8.48 1.5l.01.02q.41.37.84 1.31.38.89.63 2.08a40 40 0 0 0-3.92 0q.25-1.2.63-2.08a4 4 0 0 1 .85-1.32 7 7 0 0 1 .96 0m-2.75.4a6.5 6.5 0 0 0-3.67 3.44 29 29 0 0 1 2.7-.34q.31-1.83.97-3.1M4.58 6.28q-1.66.16-2.95.43a7 7 0 0 0 0 2.58q1.3.27 2.95.43a18 18 0 0 1 0-3.44m.17 4.71q-1.45-.12-2.69-.34a6.5 6.5 0 0 0 3.67 3.44q-.65-1.27-.98-3.1" fill="#666"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h16v16H0z"/></clipPath></defs></svg> ================ File: public/next.svg ================ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg> ================ File: public/vercel.svg ================ <svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1155 1000"><path d="m577.3 0 577.4 1000H0z" fill="#fff"/></svg> ================ File: public/window.svg ================ <svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill-rule="evenodd" clip-rule="evenodd" d="M1.5 2.5h13v10a1 1 0 0 1-1 1h-11a1 1 0 0 1-1-1zM0 1h16v11.5a2.5 2.5 0 0 1-2.5 2.5h-11A2.5 2.5 0 0 1 0 12.5zm3.75 4.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5M7 4.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0m1.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5" fill="#666"/></svg> ================ File: src/app/about/page.tsx ================ export default function About() { return ( <div className="h-screen w-screen"> <div className="w-8/12 mx-auto h-full flex flex-col justify-center items-center"> <div className="w-full flex flex-col mt-8"> <h2 className="text-xl font-bold glitch">About Me</h2> <ul className="mt-2"> <li>名前: Reibniz</li> <li>職業: データサイエンティストとか, いろいろ。</li> <li>趣味: プログラミング, 3D制作</li> <li>興味: 生成モデル, ベイズ推論, MMM</li> </ul> <h2 className="text-xl font-bold glitch mt-4">About This Site</h2> <p className="mt-2"> このサイトは、思考やアイデアを試す, 遊び場として制作していますが, ある種のポートフォリオとしても機能しています。 日々の学びや考えを記録し, 他の人と共有することで, 自分自身の成長を促進することを目的としています。 どこかの誰かの役に立てれば嬉しいです。 </p> </div> </div> </div> ); } ================ File: src/app/ai-post/page.tsx ================ export default function AiPostPage() { return ( <div className="container max-w-11/12 mx-auto px-4 py-8"> <h1 className="text-2xl font-bold">AI Post</h1> <p className="mt-4"> This is a placeholder for the AI post page. You can add your content here. </p> </div> ); } ================ File: src/app/components/background/text-background.tsx ================ const text = `This file is a merged representation of the entire codebase, combined into a single document by Repomix. ================================================================ File Summary ================================================================ Purpose: -------- This file contains a packed representation of the entire repository's contents. It is designed to be easily consumable by AI systems for analysis, code review, or other automated processes. File Format: ------------ The content is organized as follows: 1. This summary section 2. Repository information 3. Directory structure 4. Repository files (if enabled) 4. Multiple file entries, each consisting of: a. A separator line (================) b. The file path (File: path/to/file) c. Another separator line d. The full contents of the file e. A blank line Usage Guidelines: ----------------- - This file should be treated as read-only. Any changes should be made to the original repository files, not this packed version. - When processing this file, use the file path to distinguish between different files in the repository. - Be aware that this file may contain sensitive information. Handle it with the same level of security as you would the original repository. Notes: ------ - Some files may have been excluded based on .gitignore rules and Repomix's configuration - Binary files are not included in this packed representation. Please refer to the Repository Structure section for a complete list of file paths, including binary files - Files matching patterns in .gitignore are excluded - Files matching default ignore patterns are excluded - Files are sorted by Git change count (files with more changes are at the bottom) Additional Info: ---------------- ================================================================ Directory Structure ================================================================ app/ components/ layout/ footer.tsx header.tsx index.ts theme-toggle.tsx post/ card.tsx page.tsx globals.css layout.tsx page.tsx contexts/ theme.tsx public/ file.svg globe.svg next.svg vercel.svg window.svg .gitignore .repomixignore next.config.ts package.json postcss.config.mjs README.md tailwind.config.js tsconfig.json ================================================================ Files ================================================================ ================ File: app/components/layout/footer.tsx ================ "use client"; export function Footer() { const currentYear = new Date().getFullYear(); return ( <footer className="fixed top-0 left-0 h-screen flex flex-row [writing-mode:vertical-rl] justify-end text-xs"> <p className="font-serif text-gray-500 dark:text-gray-400"> &copy;2024-{currentYear} Tomoya Hirakawa All rights reserved. </p> </footer> ); } ================ File: app/components/layout/header.tsx ================ "use client"; import Link from "next/link"; export function Header() { return ( <header className="fixed top-0 right-0 h-screen px-4 py-1 flex flex-row gap-5 items-center [writing-mode:vertical-rl] font-serif"> <Link href="/" className="text-lg font-bold"> Tomoya<span className="text-green-400">. </span> Hirakawa </Link> <ul className="flex flex-row gap-3 grow justify-end"> <li> <a href="/">Home</a> </li> <li> <a href="/post">Articles</a> </li> <li> <a href="/">About</a> </li> </ul> </header> ); } ================ File: app/components/layout/index.ts ================ export * from "./header"; export * from "./footer"; export * from "./theme-toggle"; ================ File: app/components/layout/theme-toggle.tsx ================ "use client"; import { Sun, Moon } from "lucide-react"; import { useTheme } from "next-themes"; import { useEffect, useState } from "react"; export function ThemeToggle() { const { theme, setTheme } = useTheme(); const [mounted, setMounted] = useState(false); useEffect(() => { console.log("Current theme:", theme); setMounted(true); }, [theme]); if (!mounted) { return null; } return ( <button className="fixed top-0 left-0 z-10 p-2"> {theme === "dark" ? ( <Sun className="text-gray-300" onClick={() => setTheme("light")} size={24} /> ) : ( <Moon className="text-gray-600" onClick={() => setTheme("dark")} /> )} </button> ); } ================ File: app/post/card.tsx ================ export function Card() { return ( <div className="card"> <h2>Card Title</h2> <p>This is a card component.</p> </div> ); } ================ File: app/post/page.tsx ================ import { Card } from "./card"; export default function Page() { return ( <div className="@container mx-auto border"> <h1>Post List</h1> <h1>Post</h1> <Card /> </div> ); } ================ File: app/globals.css ================ @import "tailwindcss"; @tailwind base; @tailwind components; @tailwind utilities; @custom-variant dark (&:where(.dark, .dark *)); ================ File: app/layout.tsx ================ import type { Metadata } from "next"; import "./globals.css"; import { Header, Footer, ThemeToggle } from "./components/layout"; import { ThemeProvider } from "@/contexts/theme"; export const metadata: Metadata = { title: "Create Next App", description: "Generated by create next app", }; export default function RootLayout({ children, }: Readonly<{ children: React.ReactNode; }>) { return ( <html lang="ja" suppressHydrationWarning> <body className="antialiased"> <ThemeProvider> <ThemeToggle /> <Header /> {children} <Footer /> </ThemeProvider> </body> </html> ); } ================ File: app/page.tsx ================ import { TextBackground } from "./components/background/text-background"; export default function Home() { return <TextBackground />; } ================ File: contexts/theme.tsx ================ "use client"; import { ThemeProvider as NextThemeProvider } from "next-themes"; export function ThemeProvider({ children }: { children: React.ReactNode }) { const defaultTheme = "system"; console.log("ThemeProvider initialized with defaultTheme:", defaultTheme); return ( <NextThemeProvider attribute="class" defaultTheme={defaultTheme} enableSystem enableColorScheme > {children} </NextThemeProvider> ); } ================ File: public/file.svg ================ <svg fill="none" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M14.5 13.5V5.41a1 1 0 0 0-.3-.7L9.8.29A1 1 0 0 0 9.08 0H1.5v13.5A2.5 2.5 0 0 0 4 16h8a2.5 2.5 0 0 0 2.5-2.5m-1.5 0v-7H8v-5H3v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1M9.5 5V2.12L12.38 5zM5.13 5h-.62v1.25h2.12V5zm-.62 3h7.12v1.25H4.5zm.62 3h-.62v1.25h7.12V11z" clip-rule="evenodd" fill="#666" fill-rule="evenodd"/></svg> ================ File: public/globe.svg ================ <svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g clip-path="url(#a)"><path fill-rule="evenodd" clip-rule="evenodd" d="M10.27 14.1a6.5 6.5 0 0 0 3.67-3.45q-1.24.21-2.7.34-.31 1.83-.97 3.1M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16m.48-1.52a7 7 0 0 1-.96 0H7.5a4 4 0 0 1-.84-1.32q-.38-.89-.63-2.08a40 40 0 0 0 3.92 0q-.25 1.2-.63 2.08a4 4 0 0 1-.84 1.31zm2.94-4.76q1.66-.15 2.95-.43a7 7 0 0 0 0-2.58q-1.3-.27-2.95-.43a18 18 0 0 1 0 3.44m-1.27-3.54a17 17 0 0 1 0 3.64 39 39 0 0 1-4.3 0 17 17 0 0 1 0-3.64 39 39 0 0 1 4.3 0m1.1-1.17q1.45.13 2.69.34a6.5 6.5 0 0 0-3.67-3.44q.65 1.26.98 3.1M8.48 1.5l.01.02q.41.37.84 1.31.38.89.63 2.08a40 40 0 0 0-3.92 0q.25-1.2.63-2.08a4 4 0 0 1 .85-1.32 7 7 0 0 1 .96 0m-2.75.4a6.5 6.5 0 0 0-3.67 3.44 29 29 0 0 1 2.7-.34q.31-1.83.97-3.1M4.58 6.28q-1.66.16-2.95.43a7 7 0 0 0 0 2.58q1.3.27 2.95.43a18 18 0 0 1 0-3.44m.17 4.71q-1.45-.12-2.69-.34a6.5 6.5 0 0 0 3.67 3.44q-.65-1.27-.98-3.1" fill="#666"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h16v16H0z"/></clipPath></defs></svg> ================ File: public/next.svg ================ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg> ================ File: public/vercel.svg ================ <svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1155 1000"><path d="m577.3 0 577.4 1000H0z" fill="#fff"/></svg> ================ File: public/window.svg ================ <svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill-rule="evenodd" clip-rule="evenodd" d="M1.5 2.5h13v10a1 1 0 0 1-1 1h-11a1 1 0 0 1-1-1zM0 1h16v11.5a2.5 2.5 0 0 1-2.5 2.5h-11A2.5 2.5 0 0 1 0 12.5zm3.75 4.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5M7 4.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0m1.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5" fill="#666"/></svg> ================ File: .gitignore ================ # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. # dependencies /node_modules /.pnp .pnp.* .yarn/* !.yarn/patches !.yarn/plugins !.yarn/releases !.yarn/versions # testing /coverage # next.js /.next/ /out/ # production /build # misc .DS_Store *.pem # debug npm-debug.log* yarn-debug.log* yarn-error.log* .pnpm-debug.log* # env files (can opt-in for committing if needed) .env* # vercel .vercel # typescript *.tsbuildinfo next-env.d.ts ================ File: .repomixignore ================ app/components/background/text-background.tsx ================ File: next.config.ts ================ import type { NextConfig } from "next"; const nextConfig: NextConfig = { /* config options here */ }; export default nextConfig; ================ File: package.json ================ { "name": "hirakawa-site", "version": "0.1.0", "private": true, "scripts": { "dev": "next dev --turbopack", "build": "next build", "start": "next start", "lint": "next lint" }, "dependencies": { "lucide-react": "^0.503.0", "next": "15.3.1", "next-themes": "^0.4.6", "react": "^19.0.0", "react-dom": "^19.0.0" }, "devDependencies": { "@tailwindcss/postcss": "^4", "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", "tailwindcss": "^4", "typescript": "^5" } } ================ File: postcss.config.mjs ================ const config = { plugins: ["@tailwindcss/postcss"], }; export default config; ================ File: README.md ================ This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). ## Getting Started First, run the development server: ```bash npm run dev # or yarn dev # or pnpm dev # or bun dev ``` Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. ## Learn More To learn more about Next.js, take a look at the following resources: - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! ## Deploy on Vercel The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. ================ File: tailwind.config.js ================ /** @type {import('tailwindcss').Config} */ module.exports = { darkMode: "class", content: [ "./app/**/*.{js,jsx,ts,tsx}", "./contexts/**/*.{js,jsx,ts,tsx}", ], theme: { extend: {}, }, plugins: [ function ({ addVariant }) { addVariant('debug', '&'); }, ], }; ================ File: tsconfig.json ================ { "compilerOptions": { "target": "ES2017", "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, "strict": true, "noEmit": true, "esModuleInterop": true, "module": "esnext", "moduleResolution": "bundler", "resolveJsonModule": true, "isolatedModules": true, "jsx": "preserve", "incremental": true, "plugins": [ { "name": "next" } ], "paths": { "@/*": ["./*"] } }, "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], "exclude": ["node_modules"] } ================================================================ End of Codebase ================================================================`; export function TextBackground() { return ( <div className="fixed top-0 left-0 w-full h-full text-xs -z-50 text-gray-200 dark:text-gray-700 select-none overflow-y-hidden"> {text} </div> ); } ================ File: src/app/components/layout/footer.tsx ================ "use client"; export function Footer() { const currentYear = new Date().getFullYear(); return ( <footer className="fixed top-0 left-0 h-screen flex flex-row [writing-mode:vertical-rl] justify-end text-xs"> <p className="font-serif text-gray-500 dark:text-gray-400"> &copy;2024-{currentYear} Reibniz All rights reserved. </p> </footer> ); } ================ File: src/app/components/layout/header.tsx ================ "use client"; import Link from "next/link"; export function Header() { return ( <header className="fixed top-0 right-0 h-screen px-4 py-1 flex flex-row gap-5 items-center [writing-mode:vertical-rl] font-serif"> <Link href="/" className="text-lg font-bold"> 遊び場 | ASOBIBA </Link> <ul className="flex flex-row gap-3 grow justify-end"> <li> <a href="/about">About</a> </li> <li> <a href="/contact">Contact</a> </li> <li> <a href="/post">Post</a> </li> <li> <a href="/ai-post">AI Post</a> </li> </ul> </header> ); } ================ File: src/app/components/layout/index.ts ================ export * from "./header"; export * from "./footer"; export * from "./theme-toggle"; ================ File: src/app/components/layout/theme-toggle.tsx ================ "use client"; import { Sun, Moon } from "lucide-react"; import { useTheme } from "next-themes"; import { useEffect, useState } from "react"; export function ThemeToggle() { const { theme, setTheme } = useTheme(); const [mounted, setMounted] = useState(false); useEffect(() => { console.log("Current theme:", theme); setMounted(true); }, [theme]); if (!mounted) { return null; } return ( <button className="fixed top-0 left-0 z-10 p-2"> {theme === "dark" ? ( <Sun className="text-gray-300" onClick={() => setTheme("light")} size={24} /> ) : ( <Moon className="text-gray-600" onClick={() => setTheme("dark")} /> )} </button> ); } ================ File: src/app/contact/page.tsx ================ export default function ContactPage() { return ( <> <div className="container mx-auto px-4 py-20"> <h1 className="glitch text-3xl text-center mb-10">Contact</h1> <div className="max-w-2xl mx-auto bg-white/50 dark:bg-black/50 p-8 rounded-lg shadow"> <p className="mb-6">お問い合わせは以下からお願いします。</p> <div className="space-y-6"> <div> <h2 className="text-xl mb-2">Email</h2> <p>reibniz.tech[at]gmail.com</p> <p className="text-sm text-gray-500"> ※[at]を@に置き換えてください。 </p> </div> <div> <h2 className="text-xl mb-2">Twitter</h2> <p>@your_handle</p> </div> <div> <h2 className="text-xl mb-2">GitHub</h2> <p>github.com/yourusername</p> </div> </div> </div> </div> </> ); } ================ File: src/app/contexts/theme.tsx ================ "use client"; import { ThemeProvider as NextThemeProvider } from "next-themes"; export function ThemeProvider({ children }: { children: React.ReactNode }) { const defaultTheme = "dark"; console.log("ThemeProvider initialized with defaultTheme:", defaultTheme); return ( <NextThemeProvider attribute="class" defaultTheme={defaultTheme} enableSystem enableColorScheme > {children} </NextThemeProvider> ); } ================ File: src/app/post/[slug]/page.tsx ================ import { MarkdownContent } from "../markdown-content"; import { TextBackground } from "../../components/background/text-background"; export default function PostPage({ params }: { params: { slug: string } }) { return ( <> <TextBackground /> <div className="container max-w-11/12 mx-auto px-4 py-8"> <MarkdownContent slug={params.slug} /> </div> </> ); } ================ File: src/app/post/card.tsx ================ import Link from "next/link"; import Image from "next/image"; export function Card({ title, description, link, date, tags, thumbnail, }: { title: string; description: string; link: string; date?: string; tags?: string[]; thumbnail?: string; }) { return ( <div className="bg-white/50 dark:bg-black/50 shadow-lg rounded-lg overflow-hidden hover:shadow-xl transition-shadow duration-300"> {/* サムネイル画像 */} {thumbnail ? ( <div className="relative h-40 w-full"> <Image src={thumbnail} alt={title} fill className="object-cover" /> </div> ) : ( <div className="relative h-40 w-full"> <Image src={"/images/asobi-16_9-001.webp"} alt={title} fill className="object-cover" /> </div> )} <div className="p-4"> {/* タグ */} {tags && tags.length > 0 && ( <div className="flex flex-wrap gap-1 mb-2"> {tags.map((tag) => ( <span key={tag} className="px-2 py-0.5 text-xs bg-gray-200 dark:bg-gray-700 rounded-full" > {tag} </span> ))} </div> )} <h2 className="text-xl font-bold">{title}</h2> <p className="mt-2 text-sm line-clamp-2">{description}</p> {/* 公開日 */} {date && ( <p className="text-gray-500 text-xs mt-2"> 公開日: {new Date(date).toLocaleDateString("ja-JP")} </p> )} <Link href={link} className="text-blue-500 hover:underline mt-3 block text-sm" > 記事を読む &rarr; </Link> </div> </div> ); } ================ File: src/app/post/markdown-content.tsx ================ import React from "react"; import ReactMarkdown from "react-markdown"; import fs from "fs"; import path from "path"; import { notFound } from "next/navigation"; import matter from "gray-matter"; import remarkGfm from "remark-gfm"; interface MarkdownContentProps { slug: string; } export async function MarkdownContent({ slug }: MarkdownContentProps) { // マークダウンファイルのパスを構築 const filePath = path.join(process.cwd(), "src", "post", `${slug}.md`); // ファイルが存在するか確認 let fileContents; try { fileContents = fs.readFileSync(filePath, "utf8"); } catch (error) { notFound(); } // フロントマターを解析 const { data, content } = matter(fileContents); return ( <article className="prose prose-base sm:prose-sm lg:prose-lg prose-slate dark:prose-invert rounded-lg p-4 sm:p-6 lg:p-8 mx-auto max-w-none sm:max-w-3xl lg:max-w-4xl bg-white/50 dark:bg-black/50"> {data.title && ( <h1 className="text-2xl sm:text-3xl lg:text-4xl mb-4">{data.title}</h1> )} {data.date && ( <p className="text-xs sm:text-sm text-gray-500 dark:text-gray-400 mb-3"> 公開日: {new Date(data.date).toLocaleDateString("ja-JP")} {data.author && ` • 著者: ${data.author}`} </p> )} {data.tags && data.tags.length > 0 && ( <div className="flex flex-wrap gap-1 sm:gap-2 mb-4"> {data.tags.map((tag: string) => ( <span key={tag} className="px-2 py-0.5 sm:py-1 text-xs bg-gray-200 dark:bg-gray-700 rounded-full" > {tag} </span> ))} </div> )} <div className="mt-6"> <ReactMarkdown remarkPlugins={[remarkGfm]}>{content}</ReactMarkdown> </div> </article> ); } ================ File: src/app/post/page.tsx ================ import { Card } from "./card"; import { getAllPosts } from "@/app/utils/post"; export default function Page() { const posts = getAllPosts(); return ( <> <h1 className="glitch text-2xl text-center p-4">Articles</h1> <div className="w-10/12 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 mx-auto"> {posts.map((post) => ( <Card key={post.slug} title={post.title} description={post.description} link={`/post/${post.slug}`} date={post.date} tags={post.tags} thumbnail={post.thumbnail} /> ))} </div> </> ); } ================ File: src/app/utils/post.ts ================ import fs from "fs"; import path from "path"; import matter from "gray-matter"; export interface Post { slug: string; title: string; description: string; date: string; tags?: string[]; author?: string; [key: string]: any; // その他のフロントマターデータを許可 } export function getAllPosts(): Post[] { const postsDirectory = path.join(process.cwd(), "src", "post"); const filenames = fs.readdirSync(postsDirectory); console.log("filenames", filenames); const posts = filenames .filter((filename) => filename.endsWith(".md")) .map((filename) => { // ファイル名からスラッグを取得(拡張子なし) const slug = filename.replace(/.md$/, ""); // ファイルの内容を読み込む const fullPath = path.join(postsDirectory, filename); const fileContents = fs.readFileSync(fullPath, "utf8"); // gray-matterを使ってフロントマターを解析 const { data, content } = matter(fileContents); // フロントマターからメタデータを取得または代替値を使用 const post: Post = { slug, title: data.title || getTitle(content, slug), description: data.description || getDescription(content), date: data.date ? data.date.toString() : "", ...data, // その他のフロントマターデータを含める }; return post; }) .sort((a, b) => { // 日付でソート(降順) const dateA = a.date ? new Date(a.date).getTime() : 0; const dateB = b.date ? new Date(b.date).getTime() : 0; return dateB - dateA; }); return posts; } // マークダウン本文からタイトルを抽出(フロントマターがない場合のフォールバック) function getTitle(content: string, slug: string): string { const titleMatch = content.match(/^# (.*)/m); return titleMatch ? titleMatch[1] : slug; } // マークダウン本文から説明を抽出(フロントマターがない場合のフォールバック) function getDescription(content: string): string { let description = ""; const introMatch = content.match(/## はじめにs+([^ ]+)/); if (introMatch) { description = introMatch[1]; } else { // はじめにセクションがなければ、最初の段落を使用 const paragraphs = content.split(" "); if (paragraphs.length > 1) { description = paragraphs[1].replace(/*.**/, "").trim(); } } return description; } ================ File: src/mastra/agents/index.ts ================ import { google } from '@ai-sdk/google'; import { Agent } from '@mastra/core/agent'; import { Memory } from '@mastra/memory'; import { weatherTool } from '../tools'; export const weatherAgent = new Agent({ name: 'Weather Agent', instructions: ` You are a helpful weather assistant that provides accurate weather information. Your primary function is to help users get weather details for specific locations. When responding: - Always ask for a location if none is provided - If the location name isn’t in English, please translate it - If giving a location with multiple parts (e.g. "New York, NY"), use the most relevant part (e.g. "New York") - Include relevant details like humidity, wind conditions, and precipitation - Keep responses concise but informative Use the weatherTool to fetch current weather data. `, model: google('gemini-1.5-pro-latest'), tools: { weatherTool }, memory: new Memory({ options: { lastMessages: 10, semanticRecall: false, threads: { generateTitle: false, }, }, }), }); ================ File: src/mastra/tools/index.ts ================ import { createTool } from '@mastra/core/tools'; import { z } from 'zod'; interface GeocodingResponse { results: { latitude: number; longitude: number; name: string; }[]; } interface WeatherResponse { current: { time: string; temperature_2m: number; apparent_temperature: number; relative_humidity_2m: number; wind_speed_10m: number; wind_gusts_10m: number; weather_code: number; }; } export const weatherTool = createTool({ id: 'get-weather', description: 'Get current weather for a location', inputSchema: z.object({ location: z.string().describe('City name'), }), outputSchema: z.object({ temperature: z.number(), feelsLike: z.number(), humidity: z.number(), windSpeed: z.number(), windGust: z.number(), conditions: z.string(), location: z.string(), }), execute: async ({ context }) => { return await getWeather(context.location); }, }); const getWeather = async (location: string) => { const geocodingUrl = `https://geocoding-api.open-meteo.com/v1/search?name=${encodeURIComponent(location)}&count=1`; const geocodingResponse = await fetch(geocodingUrl); const geocodingData = (await geocodingResponse.json()) as GeocodingResponse; if (!geocodingData.results?.[0]) { throw new Error(`Location '${location}' not found`); } const { latitude, longitude, name } = geocodingData.results[0]; const weatherUrl = `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&current=temperature_2m,apparent_temperature,relative_humidity_2m,wind_speed_10m,wind_gusts_10m,weather_code`; const response = await fetch(weatherUrl); const data = (await response.json()) as WeatherResponse; return { temperature: data.current.temperature_2m, feelsLike: data.current.apparent_temperature, humidity: data.current.relative_humidity_2m, windSpeed: data.current.wind_speed_10m, windGust: data.current.wind_gusts_10m, conditions: getWeatherCondition(data.current.weather_code), location: name, }; }; function getWeatherCondition(code: number): string { const conditions: Record<number, string> = { 0: 'Clear sky', 1: 'Mainly clear', 2: 'Partly cloudy', 3: 'Overcast', 45: 'Foggy', 48: 'Depositing rime fog', 51: 'Light drizzle', 53: 'Moderate drizzle', 55: 'Dense drizzle', 56: 'Light freezing drizzle', 57: 'Dense freezing drizzle', 61: 'Slight rain', 63: 'Moderate rain', 65: 'Heavy rain', 66: 'Light freezing rain', 67: 'Heavy freezing rain', 71: 'Slight snow fall', 73: 'Moderate snow fall', 75: 'Heavy snow fall', 77: 'Snow grains', 80: 'Slight rain showers', 81: 'Moderate rain showers', 82: 'Violent rain showers', 85: 'Slight snow showers', 86: 'Heavy snow showers', 95: 'Thunderstorm', 96: 'Thunderstorm with slight hail', 99: 'Thunderstorm with heavy hail', }; return conditions[code] || 'Unknown'; } ================ File: src/mastra/types/daily-papers.ts ================ import { z } from "zod"; export interface Author { _id: string; user?: { _id: string; avatarUrl: string; isPro: boolean; fullname: string; user: string; type: string; }; name: string; status?: string; statusLastChangedAt?: string; hidden: boolean; } export interface Paper { id: string; authors: Author[]; publishedAt: string; submittedOnDailyAt?: string; title: string; submittedOnDailyBy?: { _id: string; avatarUrl: string; isPro: boolean; fullname: string; user: string; type: string; }; summary: string; upvotes?: number; discussionId?: string; projectPage?: string; githubRepo?: string; mediaUrls?: string[]; ai_keywords?: string[]; } export interface PaperEntry { paper: Paper; publishedAt: string; title: string; summary: string; mediaUrls?: string[]; thumbnail?: string; numComments?: number; submittedBy?: { _id: string; avatarUrl: string; fullname: string; name: string; type: string; isPro: boolean; isHf?: boolean; isHfAdmin?: boolean; isMod?: boolean; followerCount?: number; }; isAuthorParticipating?: boolean; } export interface FormatedPaper { id: string; authors: string[]; publishedAt: string; title: string; summary: string; projectPage?: string; githubRepo?: string; mediaUrls?: string[]; ai_keywords?: string[]; } export interface SummaryPaper extends FormatedPaper { aiSummary: { summary: string; comparison: string; importantPoints: string; effectiveness: string; discussion: string; nextPaper: string; }; } export interface PapersList extends Array<PaperEntry> {} export interface FormatedPapersList extends Array<FormatedPaper> {} const authorSchema = z.object({ _id: z.string(), user: z .object({ _id: z.string(), avatarUrl: z.string(), isPro: z.boolean(), fullname: z.string(), user: z.string(), type: z.string(), }) .optional(), name: z.string(), status: z.string().optional(), statusLastChangedAt: z.string().optional(), hidden: z.boolean(), }); const paperSchema = z.object({ id: z.string(), authors: z.array(authorSchema), publishedAt: z.string(), submittedOnDailyAt: z.string().optional(), title: z.string(), submittedOnDailyBy: z .object({ _id: z.string(), avatarUrl: z.string(), isPro: z.boolean(), fullname: z.string(), user: z.string(), type: z.string(), }) .optional(), summary: z.string(), upvotes: z.number().optional(), discussionId: z.string().optional(), projectPage: z.string().optional(), githubRepo: z.string().optional(), mediaUrls: z.array(z.string()).optional(), ai_keywords: z.array(z.string()).optional(), }); const paperEntrySchema = z.object({ paper: paperSchema, publishedAt: z.string(), title: z.string(), summary: z.string(), mediaUrls: z.array(z.string()).optional(), thumbnail: z.string().optional(), numComments: z.number().optional(), submittedBy: z .object({ _id: z.string(), avatarUrl: z.string(), fullname: z.string(), name: z.string(), type: z.string(), isPro: z.boolean(), isHf: z.boolean().optional(), isHfAdmin: z.boolean().optional(), isMod: z.boolean().optional(), followerCount: z.number().optional(), }) .optional(), isAuthorParticipating: z.boolean().optional(), }); const formatedPaperSchema = z.object({ id: z.string(), authors: z.array(z.string()), publishedAt: z.string(), title: z.string(), summary: z.string(), upvotes: z.number().optional(), discussionId: z.string().optional(), projectPage: z.string().optional(), githubRepo: z.string().optional(), mediaUrls: z.array(z.string()).optional(), ai_keywords: z.array(z.string()).optional(), }); const summaryPaperSchema = z.object({ id: z.string(), authors: z.array(z.string()), publishedAt: z.string(), title: z.string(), summary: z.string(), projectPage: z.string().optional(), githubRepo: z.string().optional(), mediaUrls: z.array(z.string()).optional(), ai_keywords: z.array(z.string()).optional(), aiSummary: z.object({ summary: z.string(), comparison: z.string(), importantPoints: z.string(), effectiveness: z.string(), discussion: z.string(), nextPaper: z.string(), }), }); const papersListSchema = z.array(paperEntrySchema); const formatedPapersListSchema = z.array(formatedPaperSchema); export { authorSchema, paperSchema, paperEntrySchema, formatedPaperSchema, papersListSchema, formatedPapersListSchema, summaryPaperSchema, }; ================ File: src/mastra/workflows/daily-papers-workflow.ts ================ import { Step, Workflow } from "@mastra/core/workflows"; import { z } from "zod"; import { google } from "@ai-sdk/google"; import { generateObject, generateText } from "ai"; // 型をインポート import { papersListSchema, PapersList, formatedPapersListSchema, FormatedPapersList, summaryPaperSchema, SummaryPaper, } from "../types/daily-papers"; const summaryModel = google("gemini-2.0-flash-001", {}); // huggingface.coからdailyの論文を取得する関数 const fetchDailyPapers = async (date: string) => { const requestUrl = `https://huggingface.co/api/daily_papers?date=${date}`; const dailyPapersResponse = await fetch(requestUrl); const dailyPaperData = await dailyPapersResponse.json(); if (!dailyPaperData) { throw new Error(`Date '${date}' not found`); } return dailyPaperData as PapersList; }; // 論文を取得するステップ const getDailyPapers = new Step({ id: "get-daily-papers", description: "Fetches daily papers from Hugging Face", inputSchema: z.object({ date: z.string().describe("Date for getting papers"), }), outputSchema: z.object({ papers: papersListSchema, }), execute: async ({ context }) => { const triggerData = context?.getStepResult<{ date: string }>("trigger"); if (!triggerData) { throw new Error("Trigger data not found"); } const papers = await fetchDailyPapers(triggerData.date); return { papers }; }, }); // 論文に関するデータを整形する関数 const formatPapers = (papers: PapersList): FormatedPapersList => { return papers.map((paper) => ({ id: paper.paper.id, authors: paper.paper.authors ? paper.paper.authors.map((author) => author.name || "") : [], publishedAt: paper.publishedAt, title: paper.title, summary: paper.summary, projectPage: paper.paper.projectPage, githubRepo: paper.paper.githubRepo, mediaUrls: paper.paper.mediaUrls, ai_keywords: paper.paper.ai_keywords || [], })); }; // 論文のデータを整形するステップ const formatDailyPapers = new Step({ id: "format-daily-papers", description: "Format daily papers", inputSchema: z.object({ papers: papersListSchema, }), outputSchema: z.object({ papers: formatedPapersListSchema, }), execute: async ({ context }) => { const result = context?.getStepResult<{ papers: PapersList }>( "get-daily-papers" ); if (!result || !result.papers) { throw new Error("Papers data not found"); } const formattedPapers = formatPapers(result.papers); return { papers: formattedPapers }; }, }); // 論文の要約を落合フォーマットで生成する関数 const generateSummary = async (id: string) => { const pdfUrl = `https://arxiv.org/pdf/${id}`; const response = await generateObject({ model: summaryModel, messages: [ { role: "user", content: [ { type: "text", text: `# Task Please create a summary of the given paper. When summarizing, please include the following perspectives: * What is it in one sentence? * What is impressive about it compared to previous research? * What are the important points of the technology or methodology? * How was the technology or methodology determined to be effective? * Are there any points that should be discussed or criticized? * What paper should be read next? # Output The output will be in JSON format including the above items. { summary: What is it in one sentence? comparison: What is impressive about it compared to previous research? importantPoints: What are the important points of the technology or methodology? effectiveness: How was the technology or methodology determined to be effective? discussion: Are there any points that should be discussed or criticized? nextPaper: What paper should be read next? (paper reference) } # Important Notice Please provide the output in Japanese. Is there anything else you'd like me to adjust in the translation? }`, }, { type: "file", data: new URL(pdfUrl), mimeType: "application/pdf", }, ], }, ], schema: z.object({ summary: z.string().describe("ひとことでまとめるとどんなものですか?"), comparison: z .string() .describe("先行研究と比較してどの点がすごいのですか?"), importantPoints: z .string() .describe("技術や手法の重要な点はどこにありますか?"), effectiveness: z .string() .describe("技術や手法はどのように有効だと判断されましたか?"), discussion: z.string().describe("何か議論や批判すべき点はありますか?"), nextPaper: z.string().describe("次に読むべき論文は何ですか?"), }), }); const summary = response.object; if (!summary) { throw new Error("Summary generation failed"); } return summary; }; // 論文の要約を落合フォーマットで生成するステップ const generateSummaryStep = new Step({ id: "generate-summary", description: "Generate summary for each paper", inputSchema: z.object({ papers: formatedPapersListSchema, }), outputSchema: z.object({ summaries: z.array(summaryPaperSchema), }), execute: async ({ context }) => { const result = context?.getStepResult<{ papers: FormatedPapersList }>( "format-daily-papers" ); if (!result || !result.papers) { throw new Error("Papers data not found"); } const summaries = await Promise.all( result.papers.map(async (paper) => { const summary = await generateSummary(paper.id); return { aiSummary: summary, ...paper, } as SummaryPaper; }) ); return { summaries }; }, }); // マークダウンで記事を作成する関数 const generateMarkdownArticle = async ( papers: SummaryPaper[] ): Promise<string> => { const paperInfoString = papers .map((paper) => { const { title, authors, publishedAt, summary, projectPage, githubRepo, mediaUrls, aiSummary, } = paper; const authorsString = authors.join(", "); const summaryString = aiSummary.summary; const comparisonString = aiSummary.comparison; const importantPointsString = aiSummary.importantPoints; const effectivenessString = aiSummary.effectiveness; const discussionString = aiSummary.discussion; const nextPaperString = aiSummary.nextPaper; const markdownString = ` # ${title} ## Authors ${authorsString} ## Summary ${summary} ## Published At ${publishedAt} ## Project Page ${projectPage || "N/A"} ## GitHub Repo ${githubRepo || "N/A"} ## Media URLs ${mediaUrls?.length ? mediaUrls.join(", ") : "N/A"} ## Summary (AI) ${summaryString} ## Comparison (AI) ${comparisonString} ## Important Points (AI) ${importantPointsString} ## Effectiveness (AI) ${effectivenessString} ## Discussion (AI) ${discussionString} ## Next Paper (AI) ${nextPaperString} `; return markdownString; }) .join(" --- "); const response = await generateText({ model: summaryModel, messages: [ { role: "user", content: [ { type: "text", text: `# タスク あなたには、本日のフィーチャーされた論文が複数与えられます。 その論文をもとに、マークダウン形式で記事を作成します。 記事には、以下の情報を含めてください。 `, }, { type: "text", text: paperInfoString, }, ], }, ], }); if (!response.text) { throw new Error("Markdown generation failed"); } return response.text; }; // マークダウン記事を生成するステップ const generateMarkdownArticleStep = new Step({ id: "generate-markdown-article", description: "Generate markdown article from papers", inputSchema: z.object({ summaries: z.array(summaryPaperSchema), }), outputSchema: z.object({ article: z.string().describe("Generated markdown article"), }), execute: async ({ context }) => { const result = context?.getStepResult<{ summaries: SummaryPaper[] }>( "generate-summary" ); if (!result || !result.summaries) { throw new Error("Summaries data not found"); } const article = await generateMarkdownArticle(result.summaries); return { article }; }, }); // ワークフローを定義 // 1. get-daily-papers ステップを実行して, 日付に基づいて論文を取得 // 2. format-daily-papers ステップを実行して, 取得した論文を整形 // 3. 論文のsummaryとpdfから, 落合陽一フォーマットで要約を作成 // 4. 論文のsummary, 要約から, マークダウンで記事を作成する // 5. 作成した記事をfirebaseに保存する const dailyPapersWorkflow = new Workflow({ name: "daily-papers-workflow", triggerSchema: z.object({ date: z.string().describe("Date for getting papers"), }), }) .step(getDailyPapers) .then(formatDailyPapers) .then(generateSummaryStep) .then(generateMarkdownArticleStep) .commit(); export { dailyPapersWorkflow }; ================ File: src/mastra/workflows/weather-workflow.ts ================ import { google } from "@ai-sdk/google"; import { Agent } from "@mastra/core/agent"; import { Step, Workflow } from "@mastra/core/workflows"; import { z } from "zod"; const llm = google("gemini-1.5-pro-latest"); const agent = new Agent({ name: "Weather Agent", model: llm, instructions: ` You are a local activities and travel expert who excels at weather-based planning. Analyze the weather data and provide practical activity recommendations. For each day in the forecast, structure your response exactly as follows: 📅 [Day, Month Date, Year] ═══════════════════════════ 🌡️ WEATHER SUMMARY • Conditions: [brief description] • Temperature: [X°C/Y°F to A°C/B°F] • Precipitation: [X% chance] 🌅 MORNING ACTIVITIES Outdoor: • [Activity Name] - [Brief description including specific location/route] Best timing: [specific time range] Note: [relevant weather consideration] 🌞 AFTERNOON ACTIVITIES Outdoor: • [Activity Name] - [Brief description including specific location/route] Best timing: [specific time range] Note: [relevant weather consideration] 🏠 INDOOR ALTERNATIVES • [Activity Name] - [Brief description including specific venue] Ideal for: [weather condition that would trigger this alternative] ⚠️ SPECIAL CONSIDERATIONS • [Any relevant weather warnings, UV index, wind conditions, etc.] Guidelines: - Suggest 2-3 time-specific outdoor activities per day - Include 1-2 indoor backup options - For precipitation >50%, lead with indoor activities - All activities must be specific to the location - Include specific venues, trails, or locations - Consider activity intensity based on temperature - Keep descriptions concise but informative Maintain this exact formatting for consistency, using the emoji and section headers as shown. `, }); const forecastSchema = z.array( z.object({ date: z.string(), maxTemp: z.number(), minTemp: z.number(), precipitationChance: z.number(), condition: z.string(), location: z.string(), }) ); const fetchWeather = new Step({ id: "fetch-weather", description: "Fetches weather forecast for a given city", inputSchema: z.object({ city: z.string().describe("The city to get the weather for"), }), outputSchema: forecastSchema, execute: async ({ context }) => { const triggerData = context?.getStepResult<{ city: string }>("trigger"); if (!triggerData) { throw new Error("Trigger data not found"); } const geocodingUrl = `https://geocoding-api.open-meteo.com/v1/search?name=${encodeURIComponent(triggerData.city)}&count=1`; const geocodingResponse = await fetch(geocodingUrl); const geocodingData = (await geocodingResponse.json()) as { results: { latitude: number; longitude: number; name: string }[]; }; if (!geocodingData.results?.[0]) { throw new Error(`Location '${triggerData.city}' not found`); } const { latitude, longitude, name } = geocodingData.results[0]; const weatherUrl = `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&daily=temperature_2m_max,temperature_2m_min,precipitation_probability_mean,weathercode&timezone=auto`; const response = await fetch(weatherUrl); const data = (await response.json()) as { daily: { time: string[]; temperature_2m_max: number[]; temperature_2m_min: number[]; precipitation_probability_mean: number[]; weathercode: number[]; }; }; const forecast = data.daily.time.map((date: string, index: number) => ({ date, maxTemp: data.daily.temperature_2m_max[index], minTemp: data.daily.temperature_2m_min[index], precipitationChance: data.daily.precipitation_probability_mean[index], condition: getWeatherCondition(data.daily.weathercode[index]!), location: name, })); return forecast; }, }); const planActivities = new Step({ id: "plan-activities", description: "Suggests activities based on weather conditions", execute: async ({ context, mastra }) => { const forecast = context?.getStepResult(fetchWeather); if (!forecast || forecast.length === 0) { throw new Error("Forecast data not found"); } const prompt = `Based on the following weather forecast for ${forecast[0]?.location}, suggest appropriate activities: ${JSON.stringify(forecast, null, 2)} `; const response = await agent.stream([ { role: "user", content: prompt, }, ]); let activitiesText = ""; for await (const chunk of response.textStream) { process.stdout.write(chunk); activitiesText += chunk; } return { activities: activitiesText, }; }, }); function getWeatherCondition(code: number): string { const conditions: Record<number, string> = { 0: "Clear sky", 1: "Mainly clear", 2: "Partly cloudy", 3: "Overcast", 45: "Foggy", 48: "Depositing rime fog", 51: "Light drizzle", 53: "Moderate drizzle", 55: "Dense drizzle", 61: "Slight rain", 63: "Moderate rain", 65: "Heavy rain", 71: "Slight snow fall", 73: "Moderate snow fall", 75: "Heavy snow fall", 95: "Thunderstorm", }; return conditions[code] || "Unknown"; } const weatherWorkflow = new Workflow({ name: "weather-workflow", triggerSchema: z.object({ city: z.string().describe("The city to get the weather for"), }), }) .step(fetchWeather) .then(planActivities); weatherWorkflow.commit(); export { weatherWorkflow }; ================ File: src/post/ai-future.md ================ --- title: "AIとデータサイエンスの未来" description: "人工知能(AI)とデータサイエンスの分野は急速に発展しており、私たちの生活や仕事に大きな影響を与えています。この記事では、AIとデータサイエンスの未来について考察します。" date: "2023-10-01" author: "hirakawa" tags: ["AI", "データサイエンス", "機械学習", "将来展望"] --- ## はじめに 人工知能(AI)とデータサイエンスの分野は急速に発展しており、私たちの生活や仕事に大きな影響を与えています。この記事では、AI とデータサイエンスの未来について考察します。 ## 現在のトレンド 現在、以下のようなトレンドが AI とデータサイエンスの分野で見られます: - **大規模言語モデル (LLM)**: GPT-4 などの大規模言語モデルは、テキスト生成や理解の能力を大幅に向上させています。 - **生成 AI**: 画像、音声、テキストなどを生成できる AI の発展が目覚ましいです。 - **エッジ AI**: デバイス上で直接 AI を実行することで、プライバシーやレイテンシの問題を解決する取り組みが進んでいます。 ## 将来の展望 今後 5〜10 年の間に、以下のような発展が予想されます: 1. **AI とヒトの協働**: AI はヒトの能力を拡張し、より創造的なタスクに集中できるようにサポートするツールとして進化していくでしょう。 2. **特化型 AI**: 特定のドメインに特化した AI モデルがより普及し、専門的なタスクでの性能が向上します。 3. **倫理とガバナンス**: AI の発展に伴い、倫理的な問題やガバナンスの重要性がさらに高まるでしょう。 ## まとめ AI とデータサイエンスの未来は非常に明るく、様々な可能性を秘めています。しかし、技術の発展と同時に、社会的な影響や倫理的な側面も考慮することが重要です。 ================ File: src/post/generative-models.md ================ --- title: "生成モデルの基礎" description: "生成モデル(Generative Models)は、機械学習の中でも特に注目されている分野です。この記事では、生成モデルの基本的な概念と応用について説明します。" date: "2023-10-05" author: "平川" tags: ["生成モデル", "機械学習", "GAN", "VAE", "Diffusion Models"] --- ## はじめに 生成モデル(Generative Models)は、機械学習の中でも特に注目されている分野です。この記事では、生成モデルの基本的な概念と応用について説明します。 ## 生成モデルとは 生成モデルとは、データの分布を学習し、その分布に従った新しいデータを生成することができるモデルのことです。対照的に、識別モデル(Discriminative Models)は入力データから直接ラベルや値を予測します。 ## 主な生成モデルの種類 ### GAN (Generative Adversarial Networks) GAN は 2014 年に Ian Goodfellow によって提案された生成モデルで、Generator(生成器)と Discriminator(識別器)の 2 つのネットワークが敵対的に学習を行います。 ``` Generator: 偽のデータを生成 Discriminator: 本物と偽物を識別 ``` この敵対的な学習によって、より本物に近いデータが生成できるようになります。 ### VAE (Variational Autoencoders) VAE は、データの潜在表現(latent representation)を学習し、その潜在空間から新しいデータを生成するモデルです。エンコーダとデコーダの構造を持ちます。 ### Diffusion Models 最近注目を集めている Diffusion Models は、ノイズを少しずつ除去していくことでデータを生成するアプローチです。Stable Diffusion や DALL-E 2 などの画像生成モデルに利用されています。 ## 生成モデルの応用例 - **画像生成**: 写実的な画像や芸術作品の生成 - **テキスト生成**: 文章やコードの自動生成 - **音声合成**: 人間の声や音楽の生成 - **動画生成**: 短い動画やアニメーションの生成 - **薬剤設計**: 新しい分子構造の提案 ## まとめ 生成モデルは急速に発展しており、様々な分野で革新的な応用が進んでいます。基本的な概念を理解することで、これらのテクノロジーをより深く理解し、活用することができるでしょう. ================ File: postcss.config.mjs ================ const config = { plugins: ["@tailwindcss/postcss"], }; export default config; ================ File: README.md ================ This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). ## Getting Started First, run the development server: ```bash npm run dev # or yarn dev # or pnpm dev # or bun dev ``` Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. ## Learn More To learn more about Next.js, take a look at the following resources: - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! ## Deploy on Vercel The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. ================ File: tsconfig.json ================ { "compilerOptions": { "target": "ES2017", "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, "strict": true, "noEmit": true, "esModuleInterop": true, "module": "esnext", "moduleResolution": "bundler", "resolveJsonModule": true, "isolatedModules": true, "jsx": "preserve", "incremental": true, "plugins": [ { "name": "next" } ], "paths": { "@/*": ["./src/*"] } }, "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], "exclude": ["node_modules"] } ================ File: src/app/globals.css ================ @import "tailwindcss"; @tailwind base; @tailwind components; @tailwind utilities; @custom-variant dark (&:where(.dark, .dark *)); @keyframes movement { 0% { top: 0px; left: -20px; } 15% { top: 10px; left: 10px; } 60% { top: 5px; left: -10px; } 75% { top: -5px; left: 20px; } 100% { top: 10px; left: 5px; } } .glitch { /* font-size: 5rem; */ font-weight: bold; text-transform: uppercase; position: relative; text-shadow: 0.05em 0 0 #00fffc, -0.03em -0.04em 0 #fc00ff, 0.025em 0.04em 0 #fffc00; animation: glitch 725ms infinite; } .glitch span { position: absolute; top: 0; left: 0; } .glitch span:first-child { animation: glitch 500ms infinite; clip-path: polygon(0 0, 100% 0, 100% 35%, 0 35%); transform: translate(-0.04em, -0.03em); opacity: 0.75; } .glitch span:last-child { animation: glitch 375ms infinite; clip-path: polygon(0 65%, 100% 65%, 100% 100%, 0 100%); transform: translate(0.04em, 0.03em); opacity: 0.75; } @keyframes glitch { 0% { text-shadow: 0.05em 0 0 #00fffc, -0.03em -0.04em 0 #fc00ff, 0.025em 0.04em 0 #fffc00; } 15% { text-shadow: 0.05em 0 0 #00fffc, -0.03em -0.04em 0 #fc00ff, 0.025em 0.04em 0 #fffc00; } 16% { text-shadow: -0.05em -0.025em 0 #00fffc, 0.025em 0.035em 0 #fc00ff, -0.05em -0.05em 0 #fffc00; } 49% { text-shadow: -0.05em -0.025em 0 #00fffc, 0.025em 0.035em 0 #fc00ff, -0.05em -0.05em 0 #fffc00; } 50% { text-shadow: 0.05em 0.035em 0 #00fffc, 0.03em 0 0 #fc00ff, 0 -0.04em 0 #fffc00; } 99% { text-shadow: 0.05em 0.035em 0 #00fffc, 0.03em 0 0 #fc00ff, 0 -0.04em 0 #fffc00; } 100% { text-shadow: -0.05em 0 0 #00fffc, -0.025em -0.04em 0 #fc00ff, -0.04em -0.025em 0 #fffc00; } } @plugin '@tailwindcss/typography'; ================ File: src/app/layout.tsx ================ import type { Metadata } from "next"; import "./globals.css"; import { Header, Footer, ThemeToggle } from "./components/layout"; import { ThemeProvider } from "@/app/contexts/theme"; import { TextBackground } from "./components/background/text-background"; export const metadata: Metadata = { title: "Reibniz.com", description: "Generated by create next app", }; export default function RootLayout({ children, }: Readonly<{ children: React.ReactNode; }>) { return ( <html lang="ja" suppressHydrationWarning> <body className="antialiased h-screen w-dvw overflow-x-hidden"> <ThemeProvider> <ThemeToggle /> <TextBackground /> <Header /> {children} <Footer /> </ThemeProvider> </body> </html> ); } ================ File: src/app/page.tsx ================ import { getAllPosts } from "@/app/utils/post"; import { Card } from "./post/card"; export default function Home() { const posts = getAllPosts(); return ( <div className="min-h-screen pb-16 flex flex-col items-center"> {/* ヒーローセクション */} <div className="w-11/12 mx-auto h-screen flex flex-col justify-center items-center"> <div className="font-mono text-7xl glitch mb-4" data-text="ASOBIBA"> ASOBIBA </div> <div className="text-xl mb-16"> A playground of my thoughts and ideas. </div> <div className="animate-bounce mt-8"> <svg className="w-6 h-6" fill="none" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" viewBox="0 0 24 24" stroke="currentColor" > <path d="M19 14l-7 7m0 0l-7-7m7 7V3"></path> </svg> </div> </div> {/* 記事一覧セクション */} <div className="w-11/12 flex flex-col justify-center px-4 py-12"> <h2 className="text-3xl font-bold mb-8 text-center">Latest Articles</h2> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> {posts.map((post) => ( <Card key={post.slug} title={post.title} description={post.description} link={`/post/${post.slug}`} date={post.date} tags={post.tags} thumbnail={post.thumbnail} /> ))} </div> </div> </div> ); } ================ File: src/mastra/workflows/index.ts ================ export * from "./weather-workflow"; export * from "./daily-papers-workflow"; ================ File: src/mastra/index.ts ================ import { Mastra } from "@mastra/core/mastra"; import { createLogger } from "@mastra/core/logger"; import { LibSQLStore } from "@mastra/libsql"; import { weatherWorkflow, dailyPapersWorkflow } from "./workflows"; import { weatherAgent } from "./agents"; export const mastra = new Mastra({ workflows: { weatherWorkflow, dailyPapersWorkflow }, agents: { weatherAgent }, storage: new LibSQLStore({ // stores telemetry, evals, ... into memory storage, if it needs to persist, change to file:../mastra.db url: ":memory:", }), logger: createLogger({ name: "Mastra", level: "info", }), }); ================ File: .gitignore ================ # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. # dependencies /node_modules /.pnp .pnp.* .yarn/* !.yarn/patches !.yarn/plugins !.yarn/releases !.yarn/versions # testing /coverage # next.js /.next/ /out/ # production /build # misc .DS_Store *.pem # debug npm-debug.log* yarn-debug.log* yarn-error.log* .pnpm-debug.log* # env files (can opt-in for committing if needed) .env* # vercel .vercel # typescript *.tsbuildinfo next-env.d.ts .mastra/ ================ File: next.config.ts ================ import type { NextConfig } from "next"; const nextConfig: NextConfig = { /* config options here */ serverExternalPackages: ["@mastra/*"], }; export default nextConfig; ================ File: package.json ================ { "name": "reibniz-site", "version": "0.1.0", "private": true, "scripts": { "dev": "next dev --turbopack", "dev:mastra": "mastra dev", "build": "next build", "start": "next start", "lint": "next lint" }, "dependencies": { "@ai-sdk/google": "^1.2.14", "@mastra/core": "^0.9.1", "@mastra/libsql": "^0.0.1", "@mastra/memory": "^0.3.1", "@tailwindcss/typography": "^0.5.16", "ai": "^4.3.12", "gray-matter": "^4.0.3", "lucide-react": "^0.503.0", "mastra": "^0.6.0", "next": "15.3.1", "next-themes": "^0.4.6", "react": "^19.0.0", "react-dom": "^19.0.0", "react-markdown": "^10.1.0", "remark-gfm": "^4.0.1" }, "devDependencies": { "@tailwindcss/postcss": "^4", "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", "tailwindcss": "^4", "typescript": "^5" } } ================================================================ End of Codebase ================================================================
遊び場 | ASOBIBA

Articles

サイトの運営を始めました。
essay

サイトの運営を始めました。

Reibnizです。本日よりサイトを開設したので記念の記事投稿です。

公開日: 2025/5/2

記事を読む →