feat: priority system, batch tasks, action feedback, event daemon

- Priority system: GET /api/state/priorities, POST /api/action/priority_global, POST /api/action/priority_type
- Batch system: POST /api/action/batch with per-action result tracking
- Enhanced action feedback with error codes and AI suggestions:
  cell_occupied, cell_solid, cell_occupied_by_dupe, material_shortage, etc.
- Event stream: GET /api/state/events?since=&limit= for incremental polling
- Event daemon: scripts/event_daemon.py continuously polls events,
  classifies by severity, auto-triggers analysis on critical events
- Games state now reports suffocating/starving/stressed counts
- Cell data includes isDiggable and isSafeForDupe flags
- Added 'events', 'queue', 'batch', 'priority_global', 'priority_type' CLI commands
- Added sample batch plan file
This commit is contained in:
root
2026-05-22 09:01:12 +08:00
parent 4c6a9b882f
commit a4f2062c1a
6 changed files with 1350 additions and 133 deletions

View File

@ -353,6 +353,140 @@ def cmd_harvest(args):
result = api_post('/api/action/harvest', {"x": int(args[0]), "y": int(args[1])})
print(json.dumps(result, indent=2, ensure_ascii=False))
# ---------------------------------------------------------------------------
# Event / Queue / Batch / Priority
# ---------------------------------------------------------------------------
def cmd_events(args):
"""Poll game events. Usage: events [since] [limit]"""
since = args[0] if len(args) > 0 else "0"
limit = args[1] if len(args) > 1 else "50"
data = api_get(f"/api/state/events?since={since}&limit={limit}")
if 'error' in data:
print(f"Error: {data['error']}")
return
events = data.get('events', [])
next_seq = data.get('next_seq', 0)
has_more = data.get('has_more', False)
if not events:
print("No new events.")
print(f"Next sequence: {next_seq}")
return
print(f"Events ({len(events)} new, next_seq={next_seq}, has_more={has_more}):")
print()
for e in events:
severity = e.get('severity', '?')
sev_mark = {'critical': '!!!', 'warning': '!!', 'info': 'i'}.get(severity.lower(), '?')
cat = e.get('category', '?')
title = e.get('title', '?')
msg = e.get('message', '')
cycle = e.get('cycle', '?')
entity = e.get('entity', '')
cell = e.get('cell', '')
print(f" [{sev_mark}] ({cycle}) {title}")
if msg:
print(f" {msg}")
if entity:
print(f" entity: {entity}")
if isinstance(cell, int) and cell >= 0:
print(f" cell index: {cell}")
print()
def cmd_queue(args):
"""View pending task queue. Usage: queue [batch_id]"""
params = ""
if args:
params = f"?batch_id={args[0]}"
data = api_get(f"/api/state/queue{params}")
if 'error' in data:
print(f"Error: {data['error']}")
return
print(f"Task Queue:")
print(f" Length: {data.get('queue_length', '?')}")
print(f" Batch ID: {data.get('batch_id', 'none')}")
for t in data.get('tasks', []):
print(f" - {t.get('type', '?')}: {t.get('value', '?')}")
def cmd_batch(args):
"""Execute a batch of actions. Usage: batch <json_file>"""
if not args:
print("Usage: batch <json_file>")
print(" JSON format: { \"actions\": [ { \"type\": \"build|dig|...\", ... } ] }")
return
try:
with open(args[0]) as f:
plan = json.load(f)
except Exception as e:
print(f"Error reading file: {e}")
return
result = api_post('/api/action/batch', plan)
if 'error' in result:
print(f"Error: {result['error']}")
return
print(f"Batch: {result.get('batchId', '?')}")
print(f" Total: {result.get('total', 0)}")
print(f" OK: {result.get('successCount', 0)}")
print(f" Failed: {result.get('failCount', 0)}")
print(f" Summary: {result.get('summary', '?')}")
print()
for action in result.get('actions', []):
status = 'OK' if action.get('success') else 'FAIL'
result_type = action.get('result', '?')
error = action.get('error', '')
err_msg = action.get('errorMessage', '')
suggestion = action.get('suggestion', '')
print(f" [{status}] {result_type}")
if error:
print(f" error: {error}")
if err_msg:
print(f" msg: {err_msg}")
if suggestion:
print(f" -> {suggestion}")
print()
def cmd_priority_global(args):
"""Set global priority. Usage: priority_global <target> <priority>"""
if len(args) < 2:
print("Usage: priority_global <target> <priority>")
print(" target: 'dig', 'build', 'clear', or 'all'")
print(" priority: 1 (lowest) to 9 (emergency)")
return
result = api_post('/api/action/priority_global', {
"target": args[0],
"priority": int(args[1])
})
_print_feedback(result)
def cmd_priority_type(args):
"""Set priority for a building type. Usage: priority_type <buildingType> <priority>"""
if len(args) < 2:
print("Usage: priority_type <buildingType> <priority>")
return
result = api_post('/api/action/priority_type', {
"buildingType": args[0],
"priority": int(args[1])
})
_print_feedback(result)
def _print_feedback(result):
"""Pretty-print action feedback."""
if result.get('success'):
print(f"OK: {result.get('result', 'done')}")
for k, v in result.get('data', {}).items():
print(f" {k}: {v}")
else:
print(f"FAIL: {result.get('error', 'unknown_error')}")
print(f" {result.get('errorMessage', '')}")
sug = result.get('suggestion')
if sug:
print(f" -> {sug}")
def cmd_explore(args):
"""AI-friendly exploration: reads a region and returns structured text summary."""
x = int(args[0]) if len(args) > 0 else 0
@ -432,6 +566,8 @@ COMMANDS = {
'critters': cmd_critters,
'plants': cmd_plants,
'rooms': cmd_rooms,
'queue': cmd_queue,
'events': cmd_events,
'cell': cmd_cell,
'cells': cmd_cells,
'slice': cmd_cell_slice,
@ -445,6 +581,9 @@ COMMANDS = {
'mop': cmd_mop,
'harvest': cmd_harvest,
'explore': cmd_explore,
'batch': cmd_batch,
'priority_global': cmd_priority_global,
'priority_type': cmd_priority_type,
}
if __name__ == '__main__':
@ -473,10 +612,15 @@ if __name__ == '__main__':
print(" gas <x> <y> [r] Gas analysis in radius r")
print(" explore <x> <y> <w> <h> AI-friendly region summary")
print("")
print("=== Event / Queue ===")
print(" events [since] [limit] Poll new game events")
print(" queue [batch_id] View pending task queue")
print("")
print("=== Registries (AI Reference) ===")
print(" registry buildings [f] List all building IDs with metadata")
print(" registry elements [f] List all element IDs with properties")
print(" registry techs [f] List all tech IDs with unlocks")
print(" registry priorities Show priority level meanings")
print("")
print("=== Actions ===")
print(" dig <x> <y> <w> <h> Dig area")
@ -486,5 +630,10 @@ if __name__ == '__main__':
print(" research_select <id> Select tech to research")
print(" mop <x> <y> Mop liquid")
print(" harvest <x> <y> Harvest plant")
print("")
print("=== Batch / Priority (Advanced) ===")
print(" batch <json_file> Execute batch plan")
print(" priority_global <t> <p> Set global default priority")
print(" priority_type <type> <p> Set per-building-type priority")
else:
COMMANDS[cmd](sys.argv[2:])