File size: 5,513 Bytes
b0ee7e5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# agent.py

import json
from typing import Dict, Any

from re_act import (
    get_plan_from_llm,
    think,
    act,
    store_name_email_mapping,
    extract_sender_info,
    client
)
from schemas import PlanStep
from logger import logger  # from logger.py


def run_agent():
    """
    Main REPL loop for the email agent.
    """
    logger.info("Starting Email Agent REPL...")
    print("πŸ€– Email Agent ready. Type 'exit' to quit.\n")

    while True:
        try:
            user_query = input("πŸ—¨ You: ").strip()
            logger.info("Received user input: %s", user_query)

            if user_query.lower() in ("exit", "quit"):
                logger.info("Exit command detected, shutting down agent.")
                print("πŸ‘‹ Goodbye!")
                break

            # 1) Generate plan
            try:
                plan = get_plan_from_llm(user_query)
                logger.debug("Generated plan: %s", plan)
            except Exception as e:
                logger.error("Failed to generate plan: %s", e)
                print(f"❌ Could not generate a plan: {e}")
                continue

            # print plan for user transparency
            print("\n\n plan:")
            print(plan)
            print("\n\n")

            results: Dict[str, Any] = {}

            # 2) Execute each plan step
            for step in plan.plan:
                logger.info("Processing step: %s", step.action)

                if step.action == "done":
                    logger.info("Encountered 'done' action. Plan complete.")
                    print("βœ… Plan complete.")
                    break

                try:
                    should_run, updated_step, user_prompt = think(step, results, user_query)
                    logger.debug(
                        "Think outcome for '%s': should_run=%s, updated_step=%s, user_prompt=%s",
                        step.action, should_run, updated_step, user_prompt
                    )
                except Exception as e:
                    logger.error("Error in think() for step '%s': %s", step.action, e)
                    print(f"❌ Error in planning step '{step.action}': {e}")
                    break

                # Handle user prompt (e.g., missing email mapping)
                if user_prompt:
                    logger.info("User prompt required: %s", user_prompt)
                    print(f"❓ {user_prompt}")
                    user_input = input("πŸ“§ Email: ").strip()

                    try:
                        sender_info = extract_sender_info(user_query)
                        sender_intent = sender_info.get("sender_intent", "")
                        store_name_email_mapping(sender_intent, user_input)
                        logger.info("Stored mapping: %s -> %s", sender_intent, user_input)
                        print(f"βœ… Stored mapping: {sender_intent} β†’ {user_input}")

                        # Retry current step
                        should_run, updated_step, _ = think(step, results, user_query)
                        logger.debug(
                            "Post-mapping think outcome: should_run=%s, updated_step=%s",
                            should_run, updated_step
                        )
                    except Exception as e:
                        logger.error("Error storing mapping or retrying step '%s': %s", step.action, e)
                        print(f"❌ Error storing mapping or retrying step: {e}")
                        break

                if not should_run:
                    logger.info("Skipping step: %s", step.action)
                    print(f"⏭️  Skipping `{step.action}`")
                    continue

                # Execute the action
                try:
                    output = act(updated_step)
                    results[updated_step.action] = output
                    logger.info("Action '%s' executed successfully.", updated_step.action)
                    print(f"πŸ”§ Ran `{updated_step.action}` β†’ {output}")
                except Exception as e:
                    logger.error("Error executing action '%s': %s", updated_step.action, e)
                    print(f"❌ Error running `{updated_step.action}`: {e}")
                    break

            # 3) Summarize results via LLM
            try:
                summary_rsp = client.chat.completions.create(
                    model="gpt-4o-mini",
                    temperature=0.0,
                    messages=[
                        {"role": "system", "content": "Summarize these results for the user in a friendly way."},
                        {"role": "assistant", "content": json.dumps(results)}
                    ],
                )
                summary = summary_rsp.choices[0].message.content
                logger.info("Summary generated successfully.")
                print("\nπŸ“‹ Summary:\n" + summary)
            except Exception as e:
                logger.error("Failed to generate summary: %s", e)
                print("\n❌ Failed to generate summary.")

            print("\nAnything else I can help you with?\n")

        except KeyboardInterrupt:
            logger.info("KeyboardInterrupt received, shutting down.")
            print("\nπŸ‘‹ Goodbye!")
            break
        except Exception as e:
            logger.exception("Unexpected error in REPL loop: %s", e)
            print(f"❌ Unexpected error: {e}")
            continue


if __name__ == "__main__":
    run_agent()