Files
tekton/addons/godot_ai/utils/game_log_buffer.gd
T

51 lines
1.5 KiB
GDScript

@tool
class_name McpGameLogBuffer
extends McpStructuredLogRing
## Ring buffer for game-process log lines (print, push_warning, push_error)
## ferried back from the playing game over the EngineDebugger channel.
##
## Larger cap than McpEditorLogBuffer because games can be noisy. `run_id`
## rotates each time clear_for_new_run() fires (called on the game's
## mcp:hello boot beacon), giving agents a stable cursor for "lines since
## this play started".
##
## Single-threaded — game_helper.gd drains its logger from `_process` and
## calls `append` from the main thread, so this subclass can use the base
## ring's lockless reads/writes directly.
const MAX_LINES := 2000
var _run_id := ""
func _init() -> void:
super._init(MAX_LINES)
func append(level: String, text: String, details: Dictionary = {}) -> void:
var entry := {"source": "game", "level": _coerce_level(level), "text": text}
if not details.is_empty():
entry["details"] = details.duplicate(true)
_append_entry(entry)
## Rotate the run identifier and drop all buffered entries. Called when the
## game-side autoload sends its mcp:hello beacon, marking a fresh play cycle.
## Returns the new run_id.
func clear_for_new_run() -> String:
_clear_storage()
_run_id = _generate_run_id()
return _run_id
func run_id() -> String:
return _run_id
static func _generate_run_id() -> String:
## Opaque to agents — they only check equality. Time-based is plenty
## unique within a single editor session and avoids the RNG-seed
## reproducibility footgun.
return "r%d" % Time.get_ticks_msec()