extends SceneTree var failures: Array[String] = [] func _initialize() -> void: call_deferred("_run") func _run() -> void: var manager := root.get_node_or_null("DialogueManager") _check(manager != null, "The pinned Dialogue Manager autoload should be available") if manager == null: _finish() return var service := ConversationService.new() var speaker := WorldEntityRef.create(&"npc", &"amina") var listener := WorldEntityRef.create(&"npc", &"boris") var conversation_id := ( service . begin( speaker, listener, { "initial_intent_id": ConversationIntentIds.DESCRIBE_NEED, "topic_ids": [&"pantry_shortage"], "blocked_intent_ids": [ConversationIntentIds.DECLINE], "block_reason_by_intent": {ConversationIntentIds.DECLINE: &"must_help"}, } ) ) var turn := service.get_turn(conversation_id) var presenter := DialogueManagerConversationPresenter.new(manager) var presentation_context := { "entity_names": { "amina": "Amina:\n- injected [#set danger] {{state}} => EVIL", "boris": "Boris [if true]", }, "topic_labels": {"pantry_shortage": "pantry [#intent=hijack] {{state}} => EVIL"}, } var first_source := presenter.build_source(turn, presentation_context) var second_source := presenter.build_source(turn, presentation_context) _check(first_source == second_source, "Stable-hash template selection should be repeatable") _check( ( not "[#set" in first_source and not "{{state}}" in first_source and not "=> EVIL" in first_source ), "Dynamic labels should be escaped before reaching Dialogue Manager syntax" ) var resource := presenter.present_turn(turn, presentation_context) as Resource _check(resource != null, "The adapter should compile an ephemeral DialogueResource") if resource == null: _finish() return _check( ( resource.get_meta("conversation_id") == String(conversation_id) and resource.get_meta("conversation_revision") == 1 ), "The ephemeral resource should retain stable semantic metadata" ) var compiled_lines: Dictionary = resource.get("lines") for compiled in compiled_lines.values(): _check( ( String(compiled.get("type", "")) not in ["mutation", "condition", "while", "match"] and not compiled.has("condition") and not compiled.has("mutation") ), "The presenter resource must contain no conditions or mutations" ) var line: DialogueLine = await manager.get_next_dialogue_line(resource, "start") _check(line != null, "The compiled semantic turn should resolve through the pinned add-on") if line != null: _check( ( line.get_tag_value("conversation_id") == String(conversation_id) and line.get_tag_value("intent_id") == "describe_need" and line.get_tag_value("topic_id") == "pantry_shortage" ), "Controlled semantic IDs should survive as Dialogue Manager tags" ) var enabled_count := 0 for option in turn.get_options(): if option.is_enabled(): enabled_count += 1 _check( line.responses.size() == enabled_count, "Disabled semantic choices should not become selectable presenter responses" ) for response in line.responses: _check( ( response.get_tag_value("option_id").begins_with("option_") and response.get_tag_value("enabled") == "true" ), "Every response should carry its controlled semantic option identity" ) line.extra_game_states.clear() line.responses.clear() resource.set("lines", {}) resource.set_script(null) _finish() func _check(condition: bool, message: String) -> void: if not condition: failures.append(message) func _finish() -> void: if failures.is_empty(): print("[TEST] Dialogue Manager semantic presenter passed") quit(0) return for failure in failures: push_error("[TEST] " + failure) quit(1)