event.py 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. from dataclasses import asdict
  2. from datetime import datetime
  3. from enum import Enum
  4. from typing import TYPE_CHECKING
  5. from .action import action_from_dict
  6. from .observation import observation_from_dict
  7. from .utils import remove_fields
  8. if TYPE_CHECKING:
  9. from opendevin.events.event import Event
  10. class EventSource(str, Enum):
  11. AGENT = 'agent'
  12. USER = 'user'
  13. # TODO: move `content` into `extras`
  14. TOP_KEYS = ['id', 'timestamp', 'source', 'message', 'cause', 'action', 'observation']
  15. UNDERSCORE_KEYS = ['id', 'timestamp', 'source', 'cause']
  16. DELETE_FROM_MEMORY_EXTRAS = {
  17. 'screenshot',
  18. 'dom_object',
  19. 'axtree_object',
  20. 'open_pages_urls',
  21. 'active_page_index',
  22. 'last_browser_action',
  23. 'focused_element_bid',
  24. }
  25. def event_from_dict(data) -> 'Event':
  26. evt: Event
  27. if 'action' in data:
  28. evt = action_from_dict(data)
  29. elif 'observation' in data:
  30. evt = observation_from_dict(data)
  31. else:
  32. raise ValueError('Unknown event type: ' + data)
  33. for key in UNDERSCORE_KEYS:
  34. if key in data:
  35. value = data[key]
  36. if key == 'timestamp':
  37. value = datetime.fromisoformat(value)
  38. if key == 'source':
  39. value = EventSource(value)
  40. setattr(evt, '_' + key, value)
  41. return evt
  42. def event_to_dict(event: 'Event') -> dict:
  43. props = asdict(event)
  44. d = {}
  45. for key in TOP_KEYS:
  46. if hasattr(event, key) and getattr(event, key) is not None:
  47. d[key] = getattr(event, key)
  48. elif hasattr(event, f'_{key}') and getattr(event, f'_{key}') is not None:
  49. d[key] = getattr(event, f'_{key}')
  50. if key == 'id' and d.get('id') == -1:
  51. d.pop('id', None)
  52. if key == 'timestamp' and 'timestamp' in d:
  53. d['timestamp'] = d['timestamp'].isoformat()
  54. if key == 'source' and 'source' in d:
  55. d['source'] = d['source'].value
  56. props.pop(key, None)
  57. if 'action' in d:
  58. d['args'] = props
  59. elif 'observation' in d:
  60. d['content'] = props.pop('content', '')
  61. d['extras'] = props
  62. else:
  63. raise ValueError('Event must be either action or observation')
  64. return d
  65. def event_to_memory(event: 'Event') -> dict:
  66. d = event_to_dict(event)
  67. d.pop('id', None)
  68. d.pop('cause', None)
  69. d.pop('timestamp', None)
  70. d.pop('message', None)
  71. if 'extras' in d:
  72. remove_fields(d['extras'], DELETE_FROM_MEMORY_EXTRAS)
  73. return d