diff --git a/shared/godot/companion.gd b/shared/godot/companion.gd index be6eaa5..e446158 100644 --- a/shared/godot/companion.gd +++ b/shared/godot/companion.gd @@ -14,6 +14,7 @@ const STTClientScript = preload("res://src/conversation/stt_client.gd") const TTSClientScript = preload("res://src/conversation/tts_client.gd") const LLMClientScript = preload("res://src/conversation/llm_client.gd") const OrchestratorScript = preload("res://src/conversation/conversation_orchestrator.gd") +const ConversationStoreScript = preload("res://src/conversation/conversation_store.gd") const ChatWindowScript = preload("res://src/chat/chat_window.gd") const SoundEngineScript = preload("res://src/audio/sound_engine.gd") const SoundConfigScript = preload("res://src/audio/sound_config.gd") @@ -29,6 +30,8 @@ const PREFERRED_MODELS: Array[String] = [ var _chat_window: Window var _sound_config: Node +var _orchestrator: Node +var _store: Node @onready var _avatar_root: Node3D = $AvatarRoot @onready var _camera: Camera3D = $Camera3D @@ -101,10 +104,15 @@ func setup_conversation() -> void: add_child(llm) llm.setup(CompanionConfig.llm_url, CompanionConfig.llm_model) - var orchestrator := OrchestratorScript.new() - orchestrator.name = "Orchestrator" - add_child(orchestrator) - orchestrator.setup(mic, stt, tts, llm) + _store = ConversationStoreScript.new() + _store.name = "ConversationStore" + add_child(_store) + _store.setup() + + _orchestrator = OrchestratorScript.new() + _orchestrator.name = "Orchestrator" + add_child(_orchestrator) + _orchestrator.setup(mic, stt, tts, llm, _store) _chat_window = ChatWindowScript.new() _chat_window.name = "ChatWindow" @@ -114,6 +122,10 @@ func setup_conversation() -> void: EventBus.avatar_tapped.connect(_toggle_chat_window) EventBus.chat_opened.connect(_on_chat_opened) EventBus.backend_error.connect(_on_backend_error_display) + EventBus.conversation_new_requested.connect(_on_new_conversation) + EventBus.conversation_switch_requested.connect(_on_switch_conversation) + + _restore_or_create_conversation() func play_startup_sound() -> void: @@ -193,3 +205,38 @@ func _toggle_chat_window() -> void: func _on_backend_error_display(message: String) -> void: _chat_window.show_error(message) + + +func _on_new_conversation() -> void: + _store.create_conversation() + _orchestrator.clear_history() + _chat_window.clear_conversation() + + +func _on_switch_conversation(conversation_id: String) -> void: + var messages := _store.switch_to(conversation_id) + _orchestrator.load_conversation(messages) + _chat_window.replay_messages(messages) + + +func _restore_or_create_conversation() -> void: + var active_id := _store.get_active_id() + if active_id.is_empty(): + _store.create_conversation() + return + + var messages := _store.load_conversation(active_id) + if messages.is_empty(): + _store.create_conversation() + return + + _orchestrator.load_conversation(messages) + # Defer replay so chat_window is fully in the scene tree + call_deferred("_deferred_replay", messages) + + +func _deferred_replay(messages: Variant) -> void: + var typed: Array[Dictionary] = [] + for msg: Dictionary in messages: + typed.append(msg) + _chat_window.replay_messages(typed)