Files
factorio-ai-agent/docs/plan.md
21in7 25eaa7f6cd feat: 추가된 메모리 기능으로 광맥 및 마지막 행동 저장
- 에이전트가 발견한 광맥 좌표를 `ore_patch_memory.json`에 저장하여 재시작 시 활용 가능
- 마지막 실행한 행동과 결과를 `agent_last_action_memory.json`에 저장하여 다음 상태 요약에서 참고 가능
- `state_reader.py`에서 메모리 로드 및 상태 요약에 포함
- `ai_planner.py`에서 시스템 프롬프트에 기억된 광맥 및 마지막 행동 관련 가이드 추가
- `README.md`에 새로운 메모리 기능 설명 추가
2026-03-25 23:34:25 +09:00

9.9 KiB

채굴 실패 시 제외 좌표 반복 버그 수정 계획

문제 재현/관찰

  • mine_resource에서 실패한 타일을 failed_positions에 추가한 뒤 Lua에 exclude 테이블로 전달하지만, 다음 시도에서도 동일 좌표(예: 388,2)로 다시 이동하는 로그가 발생합니다.

원인 후보

  • Lua에서 제외 판정에 쓰는 좌표 키가 string.format("%.0f,%.0f", ...) 기반인 반면, Python에서 exclude["{fx:.0f},{fy:.0f}"]를 만들 때 반올림/절삭 방식이 Lua와 1:1로 일치하지 않는 케이스가 있을 수 있습니다.
  • 이 경우 exclude[key]가 항상 false가 되어, Lua가 “가장 가까운 광석”을 계속 같은 엔티티로 반환할 수 있습니다.

변경 목표

  1. failed_positions를 “Lua 키 생성과 동일한 정수 타일 좌표(tx, ty)”로만 저장합니다.
  2. Lua에서 후보 광석 엔티티를 검사할 때도 정수 타일 좌표를 계산해 키/반환/마이닝 좌표에 일관되게 사용합니다.
  3. 그 결과, 제외한 좌표는 다음 루프에서 절대로 다시 선택되지 않도록 보장합니다.

구현 범위

  • action_executor.py
    • mine_resource 내부에서 좌표 처리 로직을 정수 타일 기반으로 통일
    • Lua 반환값을 tx,ty 정수 문자열로 변경하고 Python 파싱을 이에 맞춤

README 업데이트 계획

  • 채굴 제외(exclude) 로직이 “정수 타일 키 기반으로 통일”되도록 README의 기술/동작 설명(또는 체크리스트)을 업데이트합니다.

자원 패치 중심 오차로 인한 채굴 실패 완화 계획

문제 관찰

  • scan_resources()가 패치의 평균 중심(center_x/y)을 추천 좌표로 사용하면서, 플레이어가 해당 좌표로 이동한 직후 mine_resource의 엔티티 탐색 반경 안에서 실제 자원 엔티티를 찾지 못해 실패하는 케이스가 발생할 수 있음.

근거(팩토리오 Lua API)

  • LuaInventory.get_contents()dictionary[string -> uint]를 반환하므로, 인벤토리 판독은 name -> count 형태로 처리하는 것이 맞다.
  • 자원 엔티티의 e.position은 부동소수(MapPosition) 좌표이므로, 타일 중심/평균 중심과 실제 엔티티 좌표 간 오차가 생길 수 있다.

변경 목표

  1. scan_resources() 결과에 패치 대표 좌표를 평균 중심뿐 아니라 플레이어 기준 가장 가까운 실제 엔티티 좌표(앵커 anchor_x/yanchor_tile_x/y)로 함께 제공
  2. summarize_for_ai()에서는 평균 중심 대신 앵커 좌표 기반으로 거리/추천을 계산
  3. mine_resource 후보 엔티티 탐색 반경을 더 크게 잡아(행동 레벨) 이동 직후 실패를 흡수

구현 범위

  • state_reader.py
    • scan_resources()anchor_x/yanchor_tile_x/y 추가
    • summarize_for_ai() 거리 계산을 앵커 우선으로 변경
  • action_executor.py
    • mine_resource에서 후보 엔티티 탐색 반경을 80250으로 확장

GLM 응답 지연 원인 계측/완화 계획

문제 관찰

  • ai_planner.py에서 GLM 호출이 [GLM] 생각 중... 이후 30초~1분 이상 지연되는 현상 발생
  • JSON 파싱 실패로 인한 재시도는 가끔 발생(하지만 느림의 주 원인이 아닐 가능성도 있음)

1단계(증거 수집)

  • ai_planner.py_call_glm()에 타이밍 로그 추가
    • total: 요청 시작~콘텐츠 반환까지 전체 소요
    • http_read: HTTP 응답 본문 수신까지 소요
    • json_parse: 응답 JSON 파싱 시간
    • prompt_chars/system_chars/max_tokens: 입력 크기 동시 기록

2단계(완화: 로그 확인 후)

  • json_parse가 아니라 http_read/total이 큰 경우:
    • max_tokens를 우선 크게 줄여 생성 길이 상한 조정
    • SYSTEM_PROMPT/state_summary 길이를 더 강하게 제한
  • json_parse가 큰 경우:
    • JSON 파싱/복구 로직 비용 또는 응답 형식 편차 원인 재점검

README 업데이트

  • README.md주의사항/실행 섹션에 GLM 지연 계측 로그 출력 방식 및 파라미터 조정 힌트를 반영

Cursor Hooks - Windows sessionStart 앱 선택창 원인/해결 계획

문제 재현/관찰

  • Cursor @cursor.hooks 로그에서 sessionStart 훅 실행 중 ./hooks/session-start가 stdout JSON을 내지 못하거나, Windows에서 앱 선택창이 뜨는 현상이 관찰됨

원인 후보

  • Windows에서 확장자 없는 ./hooks/session-start를 실행할 때 bash로 해석되지 않아, OS가 실행 대신 “어떤 앱으로 열지”를 요청할 수 있음

변경 목표

  1. 프로젝트 훅은 powershell로 stdout에 JSON을 출력하도록 고정
  2. superpowers 플러그인의 Cursor 훅은 bash로 감싸 실행되도록 구성 변경

구현/검증 범위

  • E:/develop/factorio-ai-agent/.cursor/hooks.json
  • E:/develop/factorio-ai-agent/.cursor/session-start-hook.ps1
  • .../superpowers/.../hooks/hooks-cursor.json
  • 검증: Cursor 재시작 후 View -> Output -> Hooks에서 sessionStart 훅이 정상 파싱되어 OUTPUT에 JSON이 나타나는지 확인

인벤토리 캐시(메모리) 추가 계획

목표

  • 파이썬 에이전트만 종료/재실행할 때 RCON으로 인벤토리를 읽지 못하거나({} 반환) 빈 값이 나오면, 직전에 성공적으로 읽은 인벤토리를 기억해서 프롬프트에 반영한다.

정책(사용자 선택: 1번 fallback only)

  • get_inventory()가 성공적으로 읽어서 값이 비어있지 않으면 캐시를 갱신한다.
  • get_inventory() 결과가 빈 딕셔너리이면(실패/빈 값) 캐시 파일을 로드해서 대체한다.

구현 범위

  • state_reader.py
    • inventory_memory.json 로드/저장 유틸 추가
    • get_inventory() 반환값을 캐시 fallback으로 교체
  • README.md
    • 인벤토리 캐시 동작과 파일명(inventory_memory.json)을 설명

발견된 광맥 좌표 기억(메모리) 추가 계획

문제 관찰

  • explore로 광맥을 발견해도, 재실행/재계획/초기화 상황에서 동일 좌표를 다시 추천받지 못해 불필요한 탐색이 반복될 수 있음.

변경 목표

  1. 자원 엔티티(광맥)의 좌표를 ore_patch_memory.json에 ore 종류별로 여러 패치 좌표로 저장
  2. 다음 상태 요약에서 “기억된 광맥” 섹션으로 AI에게 제공
  3. LLM이 가능하면 기억된 좌표로 먼저 이동해 move -> mine_resource를 수행하도록 유도

구현 범위

  • action_executor.py
    • explore 성공 시 발견한 광맥 좌표를 파일에 갱신
  • state_reader.py
    • scan_resources() 결과로도 광맥 좌표를 ore_patch_memory.json에 갱신
    • summarize_for_ai()에 “기억된 광맥” 출력 추가
  • ai_planner.py
    • SYSTEM_PROMPT에 기억된 광맥 우선 이동 가이드 추가

README 업데이트

  • ore_patch_memory.json 파일과 동작 방식 설명 추가

에이전트 재시작 시 마지막 행동 기억(메모리) 추가 계획

문제 관찰

  • 코드를 수정하면 보통 에이전트를 재시작해야 하고, 이때 ai_planner.pyfeedback_log/직전 실패 정보가 초기화되어 같은 시행착오가 반복될 수 있음.

변경 목표

  1. 재시작 시에도 “직전에 실행했던 action”과 결과(success/message)를 파일에 저장
  2. 다음 실행의 상태 요약(state_reader.summarize_for_ai())에 “기억된 마지막 행동” 섹션을 포함
  3. LLM이 마지막 행동이 실패였다면 같은 행동을 즉시 반복하지 않도록 유도

저장 기준(확정)

  • 성공/실패 상관없이 가장 마지막으로 실행을 시도한 action 1개만 저장한다.

구현 범위

  • main.py
    • 행동 실행 직후 action/result를 agent_last_action_memory.json에 저장
  • state_reader.py
    • 재시작 시 파일을 로드해 상태 요약에 포함
  • ai_planner.py
    • SYSTEM_PROMPT에 “마지막 행동 실패 재시도 금지/원인 해결 우선” 가이드 추가

README 업데이트

  • agent_last_action_memory.json 존재/동작 설명 추가

place_entity BLOCKED 완화 계획 (인접 타일 탐색)

문제 관찰

  • 로그에서 stone-furnace 배치가 FAIL 배치 불가(내부적으로 BLOCKED)로 반복됨
  • mine_resource가 자원 엔티티 근처(종종 자원 패치 타일)로 이동한 뒤, 같은 좌표에 건물을 배치하려고 하면 Factorio의 can_place_entity 조건에 걸려 막힐 수 있음

변경 목표

  1. action_executor.pyplace_entity에서 먼저 surface.can_place_entity로 배치 가능 여부를 검사
  2. 현재 좌표 (x,y)가 불가능하면, (x,y) 주변 ±1 타일 후보(대각 포함)로 순차 시도
  3. 실제로 배치된 좌표를 결과 메시지에 포함해 이후 계획이 더 안정적으로 반복되게 함

구현 범위

  • action_executor.py
    • place_entity 로직을 (x,y) 실패 시 인접 타일 후보로 확장

README 업데이트

  • place_entityBLOCKED 시 인접 타일을 자동 탐색하도록 동작 설명 추가

GLM HTTP read timeout 대응 계획 (예외 포함 재시도)

문제 관찰

  • 로그에 TimeoutError: The read operation timed out 가 발생
  • 현재 ai_planner.py는 JSON 파싱 실패만 재시도하고, 네트워크 타임아웃/연결 오류는 별도 재시도 경로가 약함

변경 목표

  1. AIPlanner.decide()의 재시도 예외 범위를 TimeoutError, ConnectionError, urllib.error.URLError까지 확장
  2. 해당 오류가 발생하면 동일한 “plan 응답 받기” 재시도로 복구 시도
  3. 3회 연속 실패 시에는 기존과 동일하게 explore 기본 행동으로 폴백

구현 범위

  • ai_planner.py
    • decide()except 절 범위 확장 및 경고 로그 보강

README 업데이트

  • GLM read timeout/연결 오류 발생 시 재시도 동작을 주의사항에 추가