luna-chat
Health Warn
- No license — Repository has no license file
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Community trust — 31 GitHub stars
Code Pass
- Code scan — Scanned 12 files during light audit, no dangerous patterns found
Permissions Pass
- Permissions — No dangerous permissions requested
No AI report is available for this listing yet.
Discordに暮らす、自律型のパーソナルAIエージェント。会話・記憶・ハートビート・定期実行をひとつのワークスペースで
Luna
Lunaは、DiscordとローカルHTTP APIをインターフェースとして、ChatGPTのモデルを使うエージェントを自律稼働させる個人用のワークスペースエージェントです。エージェントの実行には pi を使います。入力を共通イベントに変換し、会話の管理、ホスト上のファイルシステムやコマンドの実行、記憶の蓄積、ハートビート、スケジュールタスクを単一のワークスペース内で統合処理します。
セキュリティに関する重要事項
Lunaは、Discordの利用者やローカルHTTP APIの呼び出し元をホストの実行権限から隔離しません。Bot宛てのDM、メンション可能なチャンネル、他のBotやWebhook、HTTP APIからの入力により、以下の操作が確認なしに実行される可能性があります。
- 実行ユーザーがアクセス可能なすべてのファイルシステムの読み書き
- 任意のシェルコマンドの実行、ネットワーク通信、パスワードなしsudo
- Botがアクセス可能なすべてのチャンネル・スレッド・DMへの操作
- ローカルファイルのDiscordへの添付送信
@everyoneを含むDiscordの各種メンション通知
信頼できない第三者が入力できる環境には絶対に配置しないでください。 Dockerコンテナ環境であっても、実行ユーザーにはパスワードなしsudo権限が付与されています。
動作要件
- OS: macOS / Linux(native)、または Docker(linux/amd64, linux/arm64)
- Runtime: Node.js
24.21.0, pnpm12.7.0 - その他:
- Discord Bot Token(Message Content、Guild/DM Messages、Typing 等の各種Intentが必要)
- ChatGPTのサブスクリプション(ChatGPTのアカウントでログインして使います)
- Docker Engine および Docker Compose(Docker実行時)
- Git(日次整理のコミット履歴を残す場合)
- ripgrep(エージェントが記憶やワークスペースの検索に使う)
※ Windows、ダッシュボード以外のWeb UI、HTTPヘルスチェックエンドポイント等は提供していません。
事前準備(ChatGPTへのログイン)
初回起動前に、ChatGPTへログインして資格情報を LUNA_HOME/auth/credentials.json に保存しておく必要があります。デバイスコード方式なので、表示されたURLを任意の端末のブラウザで開き、コードを入力してください。
Native環境の場合
pnpm run build
pnpm exec luna-chat login
Docker環境の場合
事前にホスト側の ./data がコンテナにマウントされる設定を確認してください。
docker compose run --rm luna-chat node dist/index.mjs login
資格情報の更新に失敗した場合は、ダッシュボードに「ChatGPT 再ログインが必要」と表示されます。同じ手順で再ログインしてください。
指示の比較(再生)
記録した会話の入力を、異なる LUNA.md・MEMORY.md で再生して振る舞いを比べられます。外へ作用するツールは実行せず、呼び出しを記録します。詳細は SPEC.md を参照してください。
pnpm exec luna-chat replay --scenes scenes.json \
--variant current=$LUNA_HOME/workspace --variant proposed=./proposed --out ./replay-out
環境変数
| 変数名 | 必須 | デフォルト値 | 説明 |
|---|---|---|---|
DISCORD_BOT_TOKEN |
はい | なし | Discord Botのトークン。シェルやcheckの子プロセスには渡されません。 |
LUNA_HOME |
いいえ | ~/.luna |
データ保存先の絶対パス。 |
LOG_LEVEL |
いいえ | info |
ログレベル(trace / debug / info / warn / error)。 |
LUNA_HTTP_HOST |
いいえ | 127.0.0.1 |
HTTP APIの待ち受けアドレス。Docker Composeではコンテナ内で0.0.0.0を使用。 |
LUNA_HTTP_PORT |
いいえ | 3000 |
HTTP APIのポート。Docker Composeではホスト側の公開ポートに使用。 |
LUNA_DASHBOARD_HOST |
いいえ | 127.0.0.1 |
ダッシュボードの待ち受けアドレス。LANへ公開する場合は0.0.0.0。 |
LUNA_DASHBOARD_PORT |
いいえ | 3001 |
ダッシュボードのポート。Docker Composeではホスト側の公開ポートに使用。 |
TZ |
いいえ | システム依存 | スケジュール等に用いるタイムゾーン。Docker環境のデフォルトはAsia/Tokyo。 |
※ LOG_LEVEL を debug または trace に設定すると、メッセージ本文やプロンプト、ツール引数などが標準出力に出力されます。既知のトークン等はマスクされますが、平文に含まれる機密情報の完全な除去は保証されません。
ディレクトリ構成
初回起動時、不足しているディレクトリやファイルが自動生成されます(既存のファイルは上書きされません)。
~/.luna/
├── config.toml
├── auth/ # ChatGPTの資格情報(credentials.json)
├── sessions/ # エージェントのセッションの記録(日付ごと)
├── state/ # 使用枠など、実行中に書き出す状態(usage.json)
└── workspace/
├── LUNA.md # エージェントの人格や会話方針
├── MEMORY.md # 長期記憶
├── memory/ # 日次会話ログ(初回の記憶保存時に自動生成)
├── HEARTBEAT.md # 定期ハートビート用チェックリスト
├── AGENDA.md # 続けたいこと・約束・関心の一覧
├── .agents/skills/ # cronやheartbeatの運用手順
│ ├── cron/SKILL.md
│ └── heartbeat/SKILL.md
└── cron.toml # 定期実行タスクの設定
config.toml の基本設定
設定ファイルでは [memory] セクションが必須です。その他の項目は省略可能で、デフォルト値が適用されます。
[memory]
enabled = true
maintenance_cron = "0 4 * * *"
[discord]
allowed_channel_ids = []
allow_dm = true
memory.enabled: アイドル終了時の記憶保存および日次整理を一括で有効/無効化します。maintenance_cron: 日次整理を実行するcronスケジュール(ローカルタイムゾーン)。- 設定変更の反映には再起動が必要です(
/luna channel add/removeによる変更を除く)。詳細は SPEC.md を参照してください。
cron.toml の設定例
[[jobs]]
id = "daily-summary"
enabled = true
kind = "recurring"
cron = "0 21 * * *"
prompt = "今日の会話を確認して、必要ならDiscordへ要約を送る"
[[jobs]]
id = "release-watch"
enabled = true
kind = "recurring"
cron = "*/30 * * * *"
check = "./scripts/check-release.sh"
prompt = "data.check_output にある新しいリリースを要約し、Discordへ報告する"
定期ジョブの check には、発火時にエージェントより先にワークスペースで実行するシェルコマンドを指定できます。終了コード0で標準出力があればその内容を check_output としてプロンプトとともに実行し、出力が空、または失敗・タイムアウト(120秒)した場合はエージェントを起動しません。詳細は SPEC.md を参照してください。
セットアップと起動
Native環境
mise install
pnpm install --frozen-lockfile
pnpm run build
pnpm exec luna-chat login # 初回のみ
DISCORD_BOT_TOKEN=... pnpm start
開発時は以下を実行します:
pnpm run dev
Docker環境
cp .env.example .env
mkdir -p data
# .env に DISCORD_BOT_TOKEN を設定
docker compose up
※ ./data ディレクトリはコンテナ内の実行ユーザーから書き込み可能である必要があります。
Discordでの利用方法
メッセージの受付条件
- 常設チャンネル:
allowed_channel_idsに登録されたチャンネルでは、Luna自身の発言を除くすべてのメッセージを受信します。 - 一時セッション: 未登録のチャンネルやスレッドでは、Lunaへのメンションによって30分間の一時セッションが開始されます。セッション継続中はメンションなしの発言も受信します。
- DM: デフォルトですべてのユーザーからのDMを受信します。
スラッシュコマンド
通常のメッセージを受信できるチャンネルやDMで利用可能です(未登録チャンネルでは一時セッション中のみ実行可能)。
/luna model [model] [effort]: 現在のセッションで使用するモデルと推論強度(reasoning effort)を変更します。/luna end: 現在のセッションを手動で終了します。処理中のターン完了を待って記憶を保存し、セッションを閉じます。/luna channel add//luna channel remove: 実行したチャンネルを常設チャンネル(allowed_channel_ids)に追加または削除します(ギルド内であれば誰でも実行可能で、設定ファイルに即座に反映されます)。
HTTP APIでの利用方法
POST http://127.0.0.1:3000/events にJSONを送ります。認証はありません。Native起動ではループバックにのみ待ち受け、Docker Composeでもホストのループバックにのみポートを公開します。LUNA_HTTP_PORT を設定した場合はURLのポートを読み替えてください。
curl -i http://127.0.0.1:3000/events \
-H 'Content-Type: application/json' \
-d '{"execution":"one_shot","response_mode":"wait","event":{"type":"sensor.changed.v1","data":{"value":24}}}'
executionは独立した実行のone_shot、またはsession_idが同じ入力で会話を共有するconversationを指定します。response_modeは受付後すぐ202とrequest_idを返すasync、または処理完了まで待つwaitを指定します。両方の実行方式で選べます。asyncの結果を後から取得するAPIはありません。event.typeは空でない文字列、event.dataは任意のJSON値です。LunaがイベントIDと時刻を付け、エージェントにはevent.data.payloadとして渡します。waitの場合、エージェントがhttp_respondツールでrequest_id、HTTPステータス、JSON本文を指定すると、その内容を処理完了後に返します。指定がなければ204、処理失敗なら500です。
会話を継続する場合は execution を conversation にし、同じ session_id を送ります。会話は通常のアイドル期限後に終了します。
curl -i http://127.0.0.1:3000/events \
-H 'Content-Type: application/json' \
-d '{"execution":"conversation","response_mode":"async","session_id":"home-automation","event":{"type":"sensor.changed.v1","data":{"value":25}}}'
ダッシュボード
http://127.0.0.1:3001/ を開くと、Lunaのいまの状態を確認できます(3秒ごとに自動更新、閲覧のみ)。
- ChatGPTの認証状態と使用枠
- 会話セッションごとのフェーズ(考え中・待機中など)と経過時間、未処理の入力
- 実行中のハートビート・スケジュール・日次整理などのイベント実行
- タスクボード(実行枠、各タスクの指示・報告・追加指示)
- 次のハートビート・日次整理・スケジュールの発火予定
- 最近の出来事(受信メッセージやツールの入力・結果を含むログ)
認証はありません。会話本文やタスクの内容が表示されるため、LUNA_DASHBOARD_HOST=0.0.0.0 でLANへ公開する場合は、そのネットワーク内の全員が閲覧できることに注意してください。Docker Composeではホストのループバックにのみ公開します。
記憶と自律運用
- セッション記憶保存: 会話が30分間途切れてアイドル状態になると、エージェントが会話内容を要約し、
memory/YYYY-MM-DD.mdに追記保存します。 - 日次整理: 指定したcron時刻(デフォルト午前4時)に専用のセッションが起動し、前回以降の日次ログや
MEMORY.md、ワークスペースを見直し、MEMORY.mdを16000文字以内の中核記憶に保ちつつ詳細をmemory/topics/へ整理します。Gitが利用可能な場合は、ローカルにコミットを作成します。 - ハートビート: 一定間隔(ランダムなインターバル)ごとに
HEARTBEAT.mdとAGENDA.mdを読み込み、チェックリストを処理したうえで、アジェンダから再開条件を満たした項目を1つ進めます。長い一手はバックグラウンドタスクへ委任します。 - スケジュール実行:
cron.tomlに定義されたジョブに基づき、指定時刻にプロンプトを実行します。定期ジョブはcheckコマンドで変化があった時だけエージェントを起動できます。 - バックグラウンドタスク: 長い調査や制作は、会話中のLunaが
task_createで作業エージェントへ委任します。会話は止まらず、作業エージェントの節目・質問・結果は依頼元の会話へ届きます。タスクはLUNA_HOME/tasks/に保存され、同時実行数は[tasks].max_concurrent(デフォルト2)で設定します。
ログとプロセス管理
ログはすべて標準出力にJSON Lines形式で出力されます。ファイル保存やログローテーション、プロセスの常駐監視は、実行環境のプロセス管理ツール(systemd、Docker等)に委ねられています。
SIGINTまたはSIGTERMを受信すると、新規メッセージの受付を停止し、処理中のタスクをすべて完了させてから正常に終了します。
開発とテスト
pnpm run format:check # フォーマット確認
pnpm run lint # 静的解析
pnpm run knip # 未使用コード検出
pnpm run typecheck # 型チェック
pnpm run test # テスト実行
pnpm run build # dist/ へビルド
docker compose build # Dockerイメージビルド
リリース手順
GitHub Actionsの release ワークフローをmainブランチから手動実行し、patch、minor、major を選択します。easy-release が最新の安定版Gitタグを基準に次のバージョンを計算し、package.json の更新後に pnpm format を実行し、整形結果を含むPull Requestを作成します。GitHubの「Settings > Actions > General > Workflow permissions」で「Allow GitHub Actions to create and approve pull requests」を有効にしてください。
準備PRをmainブランチにマージすると、リリースタグとドラフトReleaseを作成し、GHCRへDockerイメージをプッシュします。ビルドと証明の付与が成功した後、Dockerイメージの latest タグを更新してGitHub Releaseを公開します。更新対象は .github/easy-release.json で指定します。
ドキュメント一覧
- SPEC.md: 機能仕様、設定項目、エラー時の挙動などの詳細
- ARCHITECTURE.md: 内部アーキテクチャ、状態遷移、設計方針の詳細
Reviews (0)
Sign in to leave a review.
Leave a reviewNo results found