main.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. import asyncio
  2. import sys
  3. from typing import Type
  4. import agenthub # noqa F401 (we import this to get the agents registered)
  5. from opendevin.controller import AgentController
  6. from opendevin.controller.agent import Agent
  7. from opendevin.core.config import args, get_llm_config_arg
  8. from opendevin.core.schema import AgentState
  9. from opendevin.events.action import ChangeAgentStateAction, MessageAction
  10. from opendevin.events.event import Event
  11. from opendevin.events.observation import AgentStateChangedObservation
  12. from opendevin.events.stream import EventSource, EventStream, EventStreamSubscriber
  13. from opendevin.llm.llm import LLM
  14. def read_task_from_file(file_path: str) -> str:
  15. """Read task from the specified file."""
  16. with open(file_path, 'r', encoding='utf-8') as file:
  17. return file.read()
  18. def read_task_from_stdin() -> str:
  19. """Read task from stdin."""
  20. return sys.stdin.read()
  21. async def main(task_str: str = '', exit_on_message: bool = False) -> AgentState:
  22. """
  23. Main coroutine to run the agent controller with task input flexibility.
  24. It's only used when you launch opendevin backend directly via cmdline.
  25. Args:
  26. task_str: task string (optional)
  27. exit_on_message: quit if agent asks for a message from user (optional)
  28. Returns:
  29. The final agent state right before shutdown
  30. """
  31. # Determine the task source
  32. if task_str:
  33. task = task_str
  34. elif args.file:
  35. task = read_task_from_file(args.file)
  36. elif args.task:
  37. task = args.task
  38. elif not sys.stdin.isatty():
  39. task = read_task_from_stdin()
  40. else:
  41. raise ValueError('No task provided. Please specify a task through -t, -f.')
  42. # only one of model_name or llm_config is required
  43. if args.llm_config:
  44. # --llm_config
  45. # llm_config can contain any of the attributes of LLMConfig
  46. llm_config = get_llm_config_arg(args.llm_config)
  47. if llm_config is None:
  48. raise ValueError(f'Invalid toml file, cannot read {args.llm_config}')
  49. print(
  50. f'Running agent {args.agent_cls} (model: {llm_config.model}, llm_config: {llm_config}) with task: "{task}"'
  51. )
  52. # create LLM instance with the given config
  53. llm = LLM(llm_config=llm_config)
  54. else:
  55. # --model-name model_name
  56. print(
  57. f'Running agent {args.agent_cls} (model: {args.model_name}), with task: "{task}"'
  58. )
  59. llm = LLM(args.model_name)
  60. AgentCls: Type[Agent] = Agent.get_cls(args.agent_cls)
  61. agent = AgentCls(llm=llm)
  62. event_stream = EventStream()
  63. controller = AgentController(
  64. agent=agent,
  65. max_iterations=args.max_iterations,
  66. max_chars=args.max_chars,
  67. event_stream=event_stream,
  68. )
  69. await event_stream.add_event(MessageAction(content=task), EventSource.USER)
  70. await event_stream.add_event(
  71. ChangeAgentStateAction(agent_state=AgentState.RUNNING), EventSource.USER
  72. )
  73. async def on_event(event: Event):
  74. if isinstance(event, AgentStateChangedObservation):
  75. if event.agent_state == AgentState.AWAITING_USER_INPUT:
  76. action = MessageAction(content='/exit')
  77. if not exit_on_message:
  78. message = input('Request user input >> ')
  79. action = MessageAction(content=message)
  80. await event_stream.add_event(action, EventSource.USER)
  81. event_stream.subscribe(EventStreamSubscriber.MAIN, on_event)
  82. while controller.get_agent_state() not in [
  83. AgentState.FINISHED,
  84. AgentState.ERROR,
  85. AgentState.PAUSED,
  86. AgentState.STOPPED,
  87. ]:
  88. await asyncio.sleep(1) # Give back control for a tick, so the agent can run
  89. # retrieve the final state before we close the controller and agent
  90. final_agent_state = controller.get_agent_state()
  91. await controller.close()
  92. return final_agent_state
  93. if __name__ == '__main__':
  94. asyncio.run(main())