天気(Open-Meteo)と Google カレンダーのキャッシュ・分類が、日記と AI の文脈にどう効くか。entry-weather・WeatherAmPmDisplay・weather-tool などコード上の出所と、設計意図・本番運用をまとめる。
日記は「その時の空気」まで含めて思い出すと強い。だから daily-snap では 天気を取る。Open-Meteo は個人開発に優しく、キー地獄からも距離がある。要件では午前/午後みたいな粒度も前提にしていて、**「正確な気象予報」より「その日の手がかり」**として扱う。
もう一つの手がかりが Google カレンダーだ。本番ではスコープ取得まで含めて動いている、というのが自分の現状認識。ここは嘘をつきたくないので、細部はコードとコンソールで追う前提。設計として大事なのは、毎回 API を叩き続けるより キャッシュと同期状態を持つこと。04-06 前後の変更(例: 0fc3682)が、その方向性を象徴する。
04-18 は UI も太く動いていて、カレンダー周りが「見える化」される。レスポンシブ、ジャーナル草案パネル、天気地図ピッカーみたいな単語が並ぶ(例: 7689dd0)。ユーザーにとっては、設定や今日画面、詳細ページのどこかで 天気と予定が“同じ今日”として束ねられる体験が重要だ。
AI 側も同じで、予定タイトルや移動の前後を質問に変換できる。MAS の話題分類や色メタと組み合わさると、「予定から自然に会話が始まる」方向に寄せられる。ここはプロダクトの核に近い。
コードを追うなら、次のファイルが早い(パスは main ブランチ想定)。
web/src/server/entry-weather.ts の applyAmPmWeatherForEntry。緯度経度(またはフォールバック)から Open-Meteo を叩き、午前/午後スロットを weatherJson(kind: "am_pm")として daily_entries に載せる。web/src/components/weather-am-pm-display.tsx の WeatherAmPmDisplay(予報/アーカイブの表示、compact でサイドバー向けに詰める旨のコメントあり)。web/src/components/weather-location-map-picker.tsx。web/src/server/agents/weather-tool.ts。DB にキャッシュがあればそれを優先(source: "db_cached")、無ければ Open-Meteo。formatWeatherForPrompt でオーケストレータへ渡す本文を組み立て、narrativeHint で「会話の誘い方」を作る。位置の「一行」や逆ジオコーディングは 04-16 前後の流れで入っている(例: 3b63893)。天気とセットで「その日の手がかり」になる。
カレンダーの説明文まで読める設計は強いが、強い分だけ扱いは慎重にしたい。どこまでをプロンプトに混ぜるか、どこまでをメタに留めるかは、個人の安心感に直結する。だから監査ログを厚くする話とセットで考えるのが自然だ。
テキストでフローを書いておくと、あとから「どこにキャッシュを足したか」を説明しやすい。
weather-location-map-picker で緯度経度を決めるapplyAmPmWeatherForEntry が Open-Meteo を叩き、午前/午後スロットを daily_entries.weatherJson に載せるagents/weather-tool が DB の weatherJson を優先し、無ければ Open-Meteo にフォールバックWeatherAmPmDisplay が同じ weatherJson を読んで UI に出すポイントは、UI 用の保存と MAS 用の読みが同じ weatherJson を参照しうること。だから「キャッシュが効くと API を叩かない」効き方が二箇所に出る。
手がかりは多いほど嬉しいが、多いほど配線が増える。だからキャッシュと分類が要る。日記は「書く」だけじゃなくて、思い出を索引する道具でもある。
天気は「正しさ」より「思い出の裏付け」が目的。数値の細部にこだわりすぎると、プロダクトの主役がズレる。
今日画面で天気が見える所、設定の地図ピッカー、カレンダーに予定が並ぶ所、AI チャットで予定に触れている会話(個人情報はマスク)。「手がかりが同じ画面に並ぶ」ことが伝われば十分。
外部 API は気持ちよく叩きすぎると、あとで自分のレート制限が先に来る。だからキャッシュと DB の保持を先に置く。天気ツールが DB の weatherJson を優先する、みたいな話は地味だが効く。
この回のまとめは、手がかりは 取得より 保持と再利用が価値になる。カレンダーも天気も、日記の「索引」を作る部品。
次回(連載最終)は、コンテナと Cloud Build、OOM と PORT、みたいな泥臭い本番寄せの話に落とす。
daily-snap 開発ログ
前: Google ログインの先に…
次: コンテナで本番に寄せたら、ビルドが OOM で笑う(04-30 の泥)
索引: 04-02 · … 04-17
dairy-snap に MAS(マルチエージェント)を入れた理由と、オーケストレータ+サブエージェント分割の効用。04-10 前後の変更と、品質・拡張性・レイテンシのトレードオフの話。
dairy-snap を Docker / Cloud Build / Cloud Run 気味に寄せるときに踏んだ地雷の型。standalone、prisma generate、Node heap、ダミー DATABASE_URL、PORT。04-16 前後のコミット列を軸に、個人開発でもハマる点を整理する。
Google OAuth・許可リスト・JWT セッションの方針と、middleware から proxy へ寄せた経緯。HTTPS 背後での secureCookie、Docker 本番との相性。04-17 前後のコミットを手がかりに。
daily-snap の画像アップロード。最大辺2048px、AVIF優先(非対応ならWebP)の圧縮、ストレージ抽象と本番 GCS 前提。日記アプリで画像が重い問題への殴り方。
AI チャットの SSE(ストリーミング)をローカル・本番で確認した手順と、環境差分で再発しうる罠。ai_artifacts / audit_logs を厚くする理由と、本文をサーバログに出さない方針。
Prisma + Postgres で daily-snap のテーブル責務を切った話。ベクトル検索は未実装だが、エントリ・チャット・画像・ai_artifacts・memory 系をどう置くか。次に足すならどこか。