Add system memory monitoring, Bedrock support, and Discord integrations

- Add CPU/GPU memory monitoring endpoint and frontend widget
- Add Amazon Bedrock model support (API key / inference profiles) plus model selector entries
- Add Discord weather/laundry notification job (JMA forecast + LLM-generated message)
- Add Discord bot that replies to mentions via the configured LLM, with weather-aware context
- Add scheduled "useless tips" job with separate webhook and quiet-hours skip
- Switch FastAPI startup to lifespan handler, log viewer, markdown rendering, and toast UI additions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-19 00:59:38 +09:00
co-authored by Claude Sonnet 4.6
parent 903d34761c
commit 4a08ba29fa
34 changed files with 5051 additions and 160 deletions
+37 -24
View File
@@ -1,22 +1,42 @@
<script setup lang="ts">
import { ref } from 'vue'
import SessionList from './components/SessionList.vue'
import ChatWindow from './components/ChatWindow.vue'
import MessageInput from './components/MessageInput.vue'
import ModelSelector from './components/ModelSelector.vue'
import LogViewer from './components/LogViewer.vue'
import ToastList from './components/ToastList.vue'
import MemoryMonitor from './components/MemoryMonitor.vue'
const showLogs = ref(false)
</script>
<template>
<div class="app">
<SessionList />
<div class="sidebar">
<SessionList />
<MemoryMonitor />
</div>
<div class="main">
<header>
<span class="title">PlayChat</span>
<ModelSelector />
<button class="log-toggle" :class="{ active: showLogs }" @click="showLogs = !showLogs">
ログ
</button>
</header>
<ChatWindow />
<MessageInput />
<div class="body">
<div class="chat-pane">
<ChatWindow />
<MessageInput />
</div>
<div v-if="showLogs" class="log-pane">
<LogViewer />
</div>
</div>
</div>
</div>
<ToastList />
</template>
<style>
@@ -26,28 +46,21 @@ body { background: #111; color: #eee; font-family: system-ui, sans-serif; }
</style>
<style scoped>
.app {
display: flex;
height: 100vh;
}
.main {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
}
.app { display: flex; height: 100vh; }
.sidebar { display: flex; flex-direction: column; border-right: 1px solid #333; overflow: hidden; }
.main { flex: 1; display: flex; flex-direction: column; overflow: hidden; }
header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 16px;
height: 48px;
border-bottom: 1px solid #333;
background: #1a1a1a;
display: flex; align-items: center; justify-content: space-between;
padding: 0 16px; height: 48px;
border-bottom: 1px solid #333; background: #1a1a1a; flex-shrink: 0;
}
.title {
font-size: 16px;
font-weight: 600;
color: #fff;
.title { font-size: 16px; font-weight: 600; color: #fff; }
.log-toggle {
background: #2a2a2a; color: #aaa; border: 1px solid #444;
border-radius: 6px; padding: 4px 14px; font-size: 13px; cursor: pointer;
}
.log-toggle.active { background: #1d3557; color: #93c5fd; border-color: #2563eb; }
.body { flex: 1; display: flex; overflow: hidden; }
.chat-pane { flex: 1; display: flex; flex-direction: column; overflow: hidden; }
.log-pane { width: 400px; min-width: 300px; border-left: 1px solid #2a2a2a; overflow: hidden; }
</style>