feat(client): throwaway narrate harness scene + live-smoke doc
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -11,3 +11,21 @@ Put here:
|
||||
- HTTP client + fallback-degradation handling (§13)
|
||||
|
||||
Cross-cutting design (anything touching both client and api) goes in the root [`/docs`](../../docs), not here.
|
||||
|
||||
## Narrate live smoke (M2 client HTTP loop)
|
||||
|
||||
The `narrate_harness` scene is a throwaway proof of the client → `/dm/narrate`
|
||||
loop. It is not the game UI.
|
||||
|
||||
**Prereqs:** the proxy running and Ollama reachable.
|
||||
|
||||
1. Start the proxy: from `api/`, `uvicorn app.main:app --port 8000` (with the
|
||||
`.env` from `.env.example`; Ollama up at `OLLAMA_BASE_URL`).
|
||||
2. In the Godot editor, open `res://scenes/narrate_harness.tscn` and run it (F6).
|
||||
3. Click **Narrate this scene**. Expect grounded prose in the Narrator's voice
|
||||
(referencing Greywater / Brannoc / the washed-out bridge), tags stripped, and
|
||||
`facts harvested: N` with N ≥ 0.
|
||||
4. **Degraded path:** stop the proxy and click again. Expect the authored
|
||||
fallback line and `(degraded)` in the status — never an error.
|
||||
|
||||
Override the proxy URL with the `coc_rpg/proxy_base_url` project setting.
|
||||
|
||||
10
client/scenes/narrate_harness.tscn
Normal file
10
client/scenes/narrate_harness.tscn
Normal file
@@ -0,0 +1,10 @@
|
||||
[gd_scene load_steps=2 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/harness/narrate_harness.gd" id="1_harness"]
|
||||
|
||||
[node name="NarrateHarness" type="Control"]
|
||||
layout_mode = 3
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
script = ExtResource("1_harness")
|
||||
66
client/scripts/harness/narrate_harness.gd
Normal file
66
client/scripts/harness/narrate_harness.gd
Normal file
@@ -0,0 +1,66 @@
|
||||
extends Control
|
||||
## Throwaway M2 harness — the first on-screen generated prose. Wires the real
|
||||
## transport to a button and a label. NOT the game UI (a later wireframe owns
|
||||
## that). Run this scene directly (F6) with the proxy + Ollama up; see the live
|
||||
## smoke steps in client/docs/README.md.
|
||||
|
||||
const DmService = preload("res://scripts/net/dm_service.gd")
|
||||
const HttpTransport = preload("res://scripts/net/http_transport.gd")
|
||||
const FallbackLibrary = preload("res://scripts/net/fallback_library.gd")
|
||||
|
||||
var _service: DmService
|
||||
var _log: CanonLog
|
||||
var _label: RichTextLabel
|
||||
var _status: Label
|
||||
var _button: Button
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
var http := HTTPRequest.new()
|
||||
add_child(http)
|
||||
_service = DmService.new(HttpTransport.new(http), FallbackLibrary.new())
|
||||
_log = _build_scene_log()
|
||||
|
||||
var vbox := VBoxContainer.new()
|
||||
vbox.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
vbox.add_theme_constant_override("separation", 12)
|
||||
add_child(vbox)
|
||||
|
||||
_button = Button.new()
|
||||
_button.text = "Narrate this scene"
|
||||
_button.pressed.connect(_on_narrate_pressed)
|
||||
vbox.add_child(_button)
|
||||
|
||||
_label = RichTextLabel.new()
|
||||
_label.fit_content = true
|
||||
_label.custom_minimum_size = Vector2(640, 320)
|
||||
vbox.add_child(_label)
|
||||
|
||||
_status = Label.new()
|
||||
vbox.add_child(_status)
|
||||
|
||||
|
||||
func _on_narrate_pressed() -> void:
|
||||
_button.disabled = true
|
||||
_status.text = "…narrating…"
|
||||
var r := await _service.narrate(_log)
|
||||
_label.text = r.display_text
|
||||
for f in r.facts:
|
||||
_log.add_fact(f)
|
||||
_status.text = "facts harvested: %d%s" % [r.facts.size(), " (degraded)" if r.degraded else ""]
|
||||
_button.disabled = false
|
||||
|
||||
|
||||
func _build_scene_log() -> CanonLog:
|
||||
var log := CanonLog.new()
|
||||
log.player = LogPlayer.new("Aldric", "sellsword", "Fortune spits on you")
|
||||
log.set_location("greywater_docks", "the Greywater docks")
|
||||
log.party.append(PartyMember.new("brannoc_thane", "Brannoc Thane", 40))
|
||||
log.party.append(PartyMember.new("cadwyn_vell", "Cadwyn Vell", 15))
|
||||
log.push_event("Arrived at Greywater by barge before dawn")
|
||||
log.push_event("Brannoc recognised the harbourmaster and went quiet")
|
||||
log.add_fact("the eastern bridge out of Greywater is washed out")
|
||||
log.add_fact("the harbourmaster is named Oda Fenn")
|
||||
log.active_quests.append(Quest.new("find_the_ledger", "The Missing Ledger", "active", "Find who took Fenn's ledger"))
|
||||
log.add_humiliation("h_0001", "vomited on a shrine step in front of a priest", 7, 3)
|
||||
return log
|
||||
1
client/scripts/harness/narrate_harness.gd.uid
Normal file
1
client/scripts/harness/narrate_harness.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dxh7t3rdoqgq5
|
||||
Reference in New Issue
Block a user