messy2json 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- messy2json-0.1.0/PKG-INFO +214 -0
- messy2json-0.1.0/README.md +200 -0
- messy2json-0.1.0/messy2json/__init__.py +1 -0
- messy2json-0.1.0/messy2json/main.py +370 -0
- messy2json-0.1.0/messy2json.egg-info/PKG-INFO +214 -0
- messy2json-0.1.0/messy2json.egg-info/SOURCES.txt +10 -0
- messy2json-0.1.0/messy2json.egg-info/dependency_links.txt +1 -0
- messy2json-0.1.0/messy2json.egg-info/entry_points.txt +2 -0
- messy2json-0.1.0/messy2json.egg-info/requires.txt +4 -0
- messy2json-0.1.0/messy2json.egg-info/top_level.txt +1 -0
- messy2json-0.1.0/pyproject.toml +27 -0
- messy2json-0.1.0/setup.cfg +4 -0
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: messy2json
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Turns messy text (emails, notes, voice-to-text) into structured JSON using Groq LLM.
|
|
5
|
+
Project-URL: Homepage, https://github.com/hamzatahir06/Messy2JSON
|
|
6
|
+
Project-URL: Repository, https://github.com/hamzatahir06/Messy2JSON
|
|
7
|
+
Project-URL: Bug Tracker, https://github.com/hamzatahir06/Messy2JSON/issues
|
|
8
|
+
Requires-Python: >=3.12
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
Requires-Dist: groq>=1.5.0
|
|
11
|
+
Requires-Dist: rich>=13.7.0
|
|
12
|
+
Requires-Dist: pyperclip>=1.8.2
|
|
13
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
14
|
+
|
|
15
|
+
# 🤖 Messy2JSON
|
|
16
|
+
|
|
17
|
+
> **Transform messy, unstructured text into clean, structured JSON using Groq LLMs.**
|
|
18
|
+
|
|
19
|
+
Messy2JSON is a lightweight, cross-platform Python CLI that converts meeting notes, emails, chat logs, and voice-to-text transcripts into structured JSON containing a summary, action items, and deadlines. Built with reliability in mind, it validates AI responses, automatically repairs malformed outputs, and provides a seamless terminal experience.
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## ✨ Features
|
|
24
|
+
|
|
25
|
+
- 🤖 AI-powered information extraction using **Groq LLMs**
|
|
26
|
+
- 🔒 One-time API key setup with live validation
|
|
27
|
+
- 🧠 Automatic JSON self-repair using an AI reflection loop
|
|
28
|
+
- ✅ Strict schema validation for reliable output
|
|
29
|
+
- 📋 Automatic clipboard copy after successful extraction
|
|
30
|
+
- 📂 Read input from files, interactive mode, or Unix pipes
|
|
31
|
+
- 💾 Save structured JSON directly to a file
|
|
32
|
+
- 💻 Cross-platform support (Windows, macOS, Linux)
|
|
33
|
+
- ⚡ Fast, clean terminal interface powered by Rich
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## 📦 Output Format
|
|
38
|
+
|
|
39
|
+
Every input is converted into the following JSON structure:
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
{
|
|
43
|
+
"summary": "A concise summary of the input.",
|
|
44
|
+
"action_items": [
|
|
45
|
+
"Action item 1",
|
|
46
|
+
"Action item 2"
|
|
47
|
+
],
|
|
48
|
+
"deadline": "Mentioned deadline or null"
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## 🚀 Installation
|
|
55
|
+
|
|
56
|
+
### Clone the repository
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
git clone https://github.com/hamzatahir06/Messy2JSON.git
|
|
60
|
+
cd Messy2JSON
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Create a virtual environment
|
|
64
|
+
|
|
65
|
+
**Linux / macOS**
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
python -m venv venv
|
|
69
|
+
source venv/bin/activate
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**Windows**
|
|
73
|
+
|
|
74
|
+
```powershell
|
|
75
|
+
python -m venv venv
|
|
76
|
+
.\venv\Scripts\activate
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Install the package
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
pip install -e .
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
> **PyPI support is coming soon.**
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
pip install messy2json
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## ⚡ Quick Start
|
|
94
|
+
|
|
95
|
+
### Interactive Mode
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
messy2json
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Paste your text, then type:
|
|
102
|
+
|
|
103
|
+
```text
|
|
104
|
+
/do
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
to generate structured JSON.
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
### Read from a File
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
messy2json -f meeting_notes.txt
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
### Read from Standard Input
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
cat notes.txt | messy2json
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
### Save Output to a File
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
messy2json -f notes.txt -o output.json
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
### Use a Different Model
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
messy2json --model llama-3.3-70b-versatile
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## ⚙️ Configuration
|
|
144
|
+
|
|
145
|
+
During the first run, Messy2JSON securely prompts for your Groq API key, validates it online, and stores it locally using your operating system's standard configuration directory.
|
|
146
|
+
|
|
147
|
+
You can also provide configuration through environment variables.
|
|
148
|
+
|
|
149
|
+
| Variable | Description |
|
|
150
|
+
|----------|-------------|
|
|
151
|
+
| `GROQ_API_KEY` | Your Groq API key |
|
|
152
|
+
| `GROQ_MODEL` | Override the default model |
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## 📁 Project Structure
|
|
157
|
+
|
|
158
|
+
```text
|
|
159
|
+
Messy2JSON/
|
|
160
|
+
│
|
|
161
|
+
├── messy2json/
|
|
162
|
+
│ ├── __init__.py
|
|
163
|
+
│ └── main.py
|
|
164
|
+
│
|
|
165
|
+
├── pyproject.toml
|
|
166
|
+
├── README.md
|
|
167
|
+
└── LICENSE
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## 🛠 Built With
|
|
173
|
+
|
|
174
|
+
- **Python 3.12+**
|
|
175
|
+
- **Groq Python SDK**
|
|
176
|
+
- **Rich**
|
|
177
|
+
- **Pyperclip**
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## 💡 Why Messy2JSON?
|
|
182
|
+
|
|
183
|
+
Unlike basic AI wrappers, Messy2JSON is designed to produce **consistent and dependable JSON**.
|
|
184
|
+
|
|
185
|
+
It includes:
|
|
186
|
+
|
|
187
|
+
- Schema validation
|
|
188
|
+
- Automatic retry and self-correction
|
|
189
|
+
- Live API key verification
|
|
190
|
+
- Cross-platform configuration management
|
|
191
|
+
- Clipboard integration
|
|
192
|
+
- Interactive and non-interactive workflows
|
|
193
|
+
|
|
194
|
+
The goal is simple: **give developers structured output they can immediately use in automation pipelines, scripts, or applications.**
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## 📄 License
|
|
199
|
+
|
|
200
|
+
This project is licensed under the **MIT License**.
|
|
201
|
+
|
|
202
|
+
See the [LICENSE](LICENSE) file for details.
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## ⭐ Support the Project
|
|
207
|
+
|
|
208
|
+
If you find Messy2JSON useful, consider giving the repository a ⭐ on GitHub.
|
|
209
|
+
|
|
210
|
+
It helps others discover the project and motivates future development.
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
**Made with ❤️ by [Hamza Tahir](https://github.com/hamzatahir06)**
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
# 🤖 Messy2JSON
|
|
2
|
+
|
|
3
|
+
> **Transform messy, unstructured text into clean, structured JSON using Groq LLMs.**
|
|
4
|
+
|
|
5
|
+
Messy2JSON is a lightweight, cross-platform Python CLI that converts meeting notes, emails, chat logs, and voice-to-text transcripts into structured JSON containing a summary, action items, and deadlines. Built with reliability in mind, it validates AI responses, automatically repairs malformed outputs, and provides a seamless terminal experience.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## ✨ Features
|
|
10
|
+
|
|
11
|
+
- 🤖 AI-powered information extraction using **Groq LLMs**
|
|
12
|
+
- 🔒 One-time API key setup with live validation
|
|
13
|
+
- 🧠 Automatic JSON self-repair using an AI reflection loop
|
|
14
|
+
- ✅ Strict schema validation for reliable output
|
|
15
|
+
- 📋 Automatic clipboard copy after successful extraction
|
|
16
|
+
- 📂 Read input from files, interactive mode, or Unix pipes
|
|
17
|
+
- 💾 Save structured JSON directly to a file
|
|
18
|
+
- 💻 Cross-platform support (Windows, macOS, Linux)
|
|
19
|
+
- ⚡ Fast, clean terminal interface powered by Rich
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## 📦 Output Format
|
|
24
|
+
|
|
25
|
+
Every input is converted into the following JSON structure:
|
|
26
|
+
|
|
27
|
+
```json
|
|
28
|
+
{
|
|
29
|
+
"summary": "A concise summary of the input.",
|
|
30
|
+
"action_items": [
|
|
31
|
+
"Action item 1",
|
|
32
|
+
"Action item 2"
|
|
33
|
+
],
|
|
34
|
+
"deadline": "Mentioned deadline or null"
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## 🚀 Installation
|
|
41
|
+
|
|
42
|
+
### Clone the repository
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
git clone https://github.com/hamzatahir06/Messy2JSON.git
|
|
46
|
+
cd Messy2JSON
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Create a virtual environment
|
|
50
|
+
|
|
51
|
+
**Linux / macOS**
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
python -m venv venv
|
|
55
|
+
source venv/bin/activate
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Windows**
|
|
59
|
+
|
|
60
|
+
```powershell
|
|
61
|
+
python -m venv venv
|
|
62
|
+
.\venv\Scripts\activate
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Install the package
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
pip install -e .
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
> **PyPI support is coming soon.**
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
pip install messy2json
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## ⚡ Quick Start
|
|
80
|
+
|
|
81
|
+
### Interactive Mode
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
messy2json
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Paste your text, then type:
|
|
88
|
+
|
|
89
|
+
```text
|
|
90
|
+
/do
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
to generate structured JSON.
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
### Read from a File
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
messy2json -f meeting_notes.txt
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
### Read from Standard Input
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
cat notes.txt | messy2json
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
### Save Output to a File
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
messy2json -f notes.txt -o output.json
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
### Use a Different Model
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
messy2json --model llama-3.3-70b-versatile
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## ⚙️ Configuration
|
|
130
|
+
|
|
131
|
+
During the first run, Messy2JSON securely prompts for your Groq API key, validates it online, and stores it locally using your operating system's standard configuration directory.
|
|
132
|
+
|
|
133
|
+
You can also provide configuration through environment variables.
|
|
134
|
+
|
|
135
|
+
| Variable | Description |
|
|
136
|
+
|----------|-------------|
|
|
137
|
+
| `GROQ_API_KEY` | Your Groq API key |
|
|
138
|
+
| `GROQ_MODEL` | Override the default model |
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## 📁 Project Structure
|
|
143
|
+
|
|
144
|
+
```text
|
|
145
|
+
Messy2JSON/
|
|
146
|
+
│
|
|
147
|
+
├── messy2json/
|
|
148
|
+
│ ├── __init__.py
|
|
149
|
+
│ └── main.py
|
|
150
|
+
│
|
|
151
|
+
├── pyproject.toml
|
|
152
|
+
├── README.md
|
|
153
|
+
└── LICENSE
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## 🛠 Built With
|
|
159
|
+
|
|
160
|
+
- **Python 3.12+**
|
|
161
|
+
- **Groq Python SDK**
|
|
162
|
+
- **Rich**
|
|
163
|
+
- **Pyperclip**
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## 💡 Why Messy2JSON?
|
|
168
|
+
|
|
169
|
+
Unlike basic AI wrappers, Messy2JSON is designed to produce **consistent and dependable JSON**.
|
|
170
|
+
|
|
171
|
+
It includes:
|
|
172
|
+
|
|
173
|
+
- Schema validation
|
|
174
|
+
- Automatic retry and self-correction
|
|
175
|
+
- Live API key verification
|
|
176
|
+
- Cross-platform configuration management
|
|
177
|
+
- Clipboard integration
|
|
178
|
+
- Interactive and non-interactive workflows
|
|
179
|
+
|
|
180
|
+
The goal is simple: **give developers structured output they can immediately use in automation pipelines, scripts, or applications.**
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## 📄 License
|
|
185
|
+
|
|
186
|
+
This project is licensed under the **MIT License**.
|
|
187
|
+
|
|
188
|
+
See the [LICENSE](LICENSE) file for details.
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## ⭐ Support the Project
|
|
193
|
+
|
|
194
|
+
If you find Messy2JSON useful, consider giving the repository a ⭐ on GitHub.
|
|
195
|
+
|
|
196
|
+
It helps others discover the project and motivates future development.
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
**Made with ❤️ by [Hamza Tahir](https://github.com/hamzatahir06)**
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# messy2json
|
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
messy2json
|
|
4
|
+
----------
|
|
5
|
+
Global CLI tool. Paste any messy text — email, meeting notes, voice-to-text —
|
|
6
|
+
and get back strict JSON: {summary, action_items, deadline}
|
|
7
|
+
|
|
8
|
+
Usage (after pip install .):
|
|
9
|
+
messy2json # interactive loop
|
|
10
|
+
messy2json -f notes.txt # read from file
|
|
11
|
+
cat notes.txt | messy2json # pipe input
|
|
12
|
+
messy2json -f notes.txt -o out.json # save result to file
|
|
13
|
+
|
|
14
|
+
API key is safely stored in the platform-appropriate system config directory.
|
|
15
|
+
Override anytime by setting the GROQ_API_KEY environment variable.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
import argparse
|
|
19
|
+
import json
|
|
20
|
+
import os
|
|
21
|
+
import pathlib
|
|
22
|
+
import sys
|
|
23
|
+
import time
|
|
24
|
+
|
|
25
|
+
from groq import Groq
|
|
26
|
+
from rich.console import Console
|
|
27
|
+
from rich.panel import Panel
|
|
28
|
+
from rich.syntax import Syntax
|
|
29
|
+
|
|
30
|
+
try:
|
|
31
|
+
import pyperclip
|
|
32
|
+
CLIPBOARD_AVAILABLE = True
|
|
33
|
+
except ImportError:
|
|
34
|
+
CLIPBOARD_AVAILABLE = False
|
|
35
|
+
|
|
36
|
+
console = Console()
|
|
37
|
+
|
|
38
|
+
# ── config paths (Cross-Platform Compliant) ──────────────────────────────────
|
|
39
|
+
if os.name == "nt": # Windows
|
|
40
|
+
CONFIG_DIR = pathlib.Path(os.environ.get("APPDATA", pathlib.Path.home())) / "messy2json"
|
|
41
|
+
else: # macOS / Linux
|
|
42
|
+
CONFIG_DIR = pathlib.Path.home() / ".config" / "messy2json"
|
|
43
|
+
|
|
44
|
+
CONFIG_FILE = CONFIG_DIR / "config.json"
|
|
45
|
+
|
|
46
|
+
DEFAULT_MODEL = "llama-3.3-70b-versatile"
|
|
47
|
+
MAX_ATTEMPTS = 3
|
|
48
|
+
REQUIRED_KEYS = {"summary", "action_items", "deadline"}
|
|
49
|
+
|
|
50
|
+
SYSTEM_PROMPT = """You are a strict information-extraction engine.
|
|
51
|
+
|
|
52
|
+
You will be given raw, possibly messy text: an email, meeting notes, or a rambling
|
|
53
|
+
voice-to-text transcript. It may contain typos, filler words, run-on sentences, or
|
|
54
|
+
no clear structure at all.
|
|
55
|
+
|
|
56
|
+
Extract exactly this JSON object and return NOTHING else - no markdown fences, no
|
|
57
|
+
commentary, no preamble, no explanation:
|
|
58
|
+
|
|
59
|
+
{
|
|
60
|
+
"summary": "one to three sentence plain-English summary of what the text is about",
|
|
61
|
+
"action_items": ["short actionable task", "another task"],
|
|
62
|
+
"deadline": "the deadline mentioned in the text (in its own words), or null if none is mentioned"
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
Rules:
|
|
66
|
+
- Output ONLY that JSON object.
|
|
67
|
+
- "action_items" is always a JSON array of strings. Use [] if there are none.
|
|
68
|
+
- "deadline" is always a JSON string or JSON null. Never omit the key, never use "N/A" or "".
|
|
69
|
+
- Never add any key other than summary, action_items, deadline.
|
|
70
|
+
- Even if the text is garbled, very short, or nearly empty, still return the full
|
|
71
|
+
JSON object with your best-effort summary and empty/null values where nothing
|
|
72
|
+
was found. Do not refuse and do not error out.
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
# ── config manager ────────────────────────────────────────────────────────────
|
|
77
|
+
|
|
78
|
+
def _load_config() -> dict:
|
|
79
|
+
try:
|
|
80
|
+
return json.loads(CONFIG_FILE.read_text())
|
|
81
|
+
except Exception:
|
|
82
|
+
return {}
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _save_config(data: dict):
|
|
86
|
+
CONFIG_DIR.mkdir(parents=True, exist_ok=True)
|
|
87
|
+
CONFIG_FILE.write_text(json.dumps(data, indent=2))
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def _first_time_setup() -> str:
|
|
91
|
+
console.print()
|
|
92
|
+
console.print(
|
|
93
|
+
Panel(
|
|
94
|
+
"No API key found.\n\n"
|
|
95
|
+
"Get a free key at [bold cyan]https://console.groq.com[/bold cyan]\n"
|
|
96
|
+
"[dim](no credit card needed — sign up and click API Keys)[/dim]\n\n"
|
|
97
|
+
"Your key will be securely saved to your local system configuration\n"
|
|
98
|
+
"directory and never asked again.",
|
|
99
|
+
title="[bold yellow]⚙ First Time Setup[/bold yellow]",
|
|
100
|
+
border_style="yellow",
|
|
101
|
+
expand=False,
|
|
102
|
+
)
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
while True:
|
|
106
|
+
try:
|
|
107
|
+
key = input("\n Enter your Groq API key: ").strip()
|
|
108
|
+
except KeyboardInterrupt:
|
|
109
|
+
console.print("\n[dim]Setup cancelled.[/dim]")
|
|
110
|
+
sys.exit(0)
|
|
111
|
+
|
|
112
|
+
if not key:
|
|
113
|
+
console.print("[bold red]✗[/bold red] No key entered. Please try again or press Ctrl+C to exit.")
|
|
114
|
+
continue
|
|
115
|
+
|
|
116
|
+
# Live authentication check over the network before committing to disk
|
|
117
|
+
with console.status("[bold yellow]Validating API key with Groq...[/bold yellow]", spinner="dots"):
|
|
118
|
+
try:
|
|
119
|
+
test_client = Groq(api_key=key)
|
|
120
|
+
test_client.chat.completions.create(
|
|
121
|
+
model=DEFAULT_MODEL,
|
|
122
|
+
messages=[{"role": "user", "content": "ping"}],
|
|
123
|
+
max_tokens=1,
|
|
124
|
+
)
|
|
125
|
+
break # Validation passed! Exit the authentication loop
|
|
126
|
+
except Exception as e:
|
|
127
|
+
console.print(f"\n[bold red]✗[/bold red] Authentication failed! The API key is invalid.")
|
|
128
|
+
console.print(f"[dim]Groq API Error: {e}[/dim]")
|
|
129
|
+
console.print("[bold yellow] Please double-check your key and try again.[/bold yellow]\n")
|
|
130
|
+
|
|
131
|
+
_save_config({"api_key": key, "model": DEFAULT_MODEL})
|
|
132
|
+
console.print("[bold green]✓[/bold green] Key verified and saved successfully!\n")
|
|
133
|
+
return key
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def get_api_key() -> str:
|
|
137
|
+
"""Priority: env var → config file → first-time setup prompt."""
|
|
138
|
+
key = os.environ.get("GROQ_API_KEY", "").strip()
|
|
139
|
+
if key:
|
|
140
|
+
return key
|
|
141
|
+
|
|
142
|
+
key = _load_config().get("api_key", "").strip()
|
|
143
|
+
if key:
|
|
144
|
+
return key
|
|
145
|
+
|
|
146
|
+
return _first_time_setup()
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def get_model() -> str:
|
|
150
|
+
"""Read model from config file, fall back to default."""
|
|
151
|
+
env_model = os.environ.get("GROQ_MODEL", "").strip()
|
|
152
|
+
if env_model:
|
|
153
|
+
return env_model
|
|
154
|
+
return _load_config().get("model", DEFAULT_MODEL)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
# ── core extraction ───────────────────────────────────────────────────────────
|
|
158
|
+
|
|
159
|
+
def _safe_fallback(reason: str) -> dict:
|
|
160
|
+
return {
|
|
161
|
+
"summary": f"Could not process input: {reason}",
|
|
162
|
+
"action_items": [],
|
|
163
|
+
"deadline": None,
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def _validate(data) -> tuple[bool, str]:
|
|
168
|
+
if not isinstance(data, dict):
|
|
169
|
+
return False, "top-level JSON is not an object"
|
|
170
|
+
missing = REQUIRED_KEYS - data.keys()
|
|
171
|
+
if missing:
|
|
172
|
+
return False, f"missing keys: {sorted(missing)}"
|
|
173
|
+
if not isinstance(data["summary"], str):
|
|
174
|
+
return False, "'summary' must be a string"
|
|
175
|
+
if not isinstance(data["action_items"], list) or not all(
|
|
176
|
+
isinstance(x, str) for x in data["action_items"]
|
|
177
|
+
):
|
|
178
|
+
return False, "'action_items' must be a list of strings"
|
|
179
|
+
if data["deadline"] is not None and not isinstance(data["deadline"], str):
|
|
180
|
+
return False, "'deadline' must be a string or null"
|
|
181
|
+
return True, ""
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def extract_json(raw_text: str, client: Groq, model: str) -> dict:
|
|
185
|
+
if not raw_text or not raw_text.strip():
|
|
186
|
+
return _safe_fallback("empty input")
|
|
187
|
+
|
|
188
|
+
messages = [
|
|
189
|
+
{"role": "system", "content": SYSTEM_PROMPT},
|
|
190
|
+
{"role": "user", "content": raw_text},
|
|
191
|
+
]
|
|
192
|
+
|
|
193
|
+
last_error = "unknown error"
|
|
194
|
+
for attempt in range(1, MAX_ATTEMPTS + 1):
|
|
195
|
+
try:
|
|
196
|
+
response = client.chat.completions.create(
|
|
197
|
+
model=model,
|
|
198
|
+
messages=messages,
|
|
199
|
+
response_format={"type": "json_object"},
|
|
200
|
+
temperature=0.2,
|
|
201
|
+
max_tokens=1024,
|
|
202
|
+
)
|
|
203
|
+
content = response.choices[0].message.content
|
|
204
|
+
|
|
205
|
+
try:
|
|
206
|
+
data = json.loads(content)
|
|
207
|
+
except json.JSONDecodeError as e:
|
|
208
|
+
last_error = f"invalid JSON syntax ({e})"
|
|
209
|
+
messages.append({"role": "assistant", "content": content})
|
|
210
|
+
messages.append({
|
|
211
|
+
"role": "user",
|
|
212
|
+
"content": (
|
|
213
|
+
f"That was not valid JSON ({e}). Reply again with ONLY the "
|
|
214
|
+
"corrected JSON object, no other text."
|
|
215
|
+
),
|
|
216
|
+
})
|
|
217
|
+
continue
|
|
218
|
+
|
|
219
|
+
ok, err = _validate(data)
|
|
220
|
+
if ok:
|
|
221
|
+
return {k: data[k] for k in REQUIRED_KEYS}
|
|
222
|
+
|
|
223
|
+
last_error = f"schema mismatch ({err})"
|
|
224
|
+
messages.append({"role": "assistant", "content": content})
|
|
225
|
+
messages.append({
|
|
226
|
+
"role": "user",
|
|
227
|
+
"content": (
|
|
228
|
+
f"That JSON didn't match the required schema ({err}). Reply again "
|
|
229
|
+
"with ONLY the corrected JSON object, no other text."
|
|
230
|
+
),
|
|
231
|
+
})
|
|
232
|
+
|
|
233
|
+
except Exception as e:
|
|
234
|
+
last_error = str(e)
|
|
235
|
+
if attempt < MAX_ATTEMPTS:
|
|
236
|
+
time.sleep(1.5 * attempt)
|
|
237
|
+
|
|
238
|
+
return _safe_fallback(last_error)
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
# ── UI helpers ────────────────────────────────────────────────────────────────
|
|
242
|
+
|
|
243
|
+
def show_banner(model: str):
|
|
244
|
+
console.print()
|
|
245
|
+
console.print(
|
|
246
|
+
Panel(
|
|
247
|
+
"[bold]messy2json[/bold]\n"
|
|
248
|
+
"Paste any messy text — email, meeting notes, voice-to-text — "
|
|
249
|
+
"and get back structured JSON.\n\n"
|
|
250
|
+
f"[dim]Model :[/dim] [yellow]{model}[/yellow]\n"
|
|
251
|
+
"[dim]Output :[/dim] [cyan]summary[/cyan] [cyan]action_items[/cyan] [cyan]deadline[/cyan]\n"
|
|
252
|
+
"[dim]GitHub :[/dim] [bold link=https://github.com/hamzatahir06/Messy2JSON]https://github.com/hamzatahir06/Messy2JSON[/bold link]",
|
|
253
|
+
title="[bold green]🤖 Agent Ready[/bold green]",
|
|
254
|
+
border_style="green",
|
|
255
|
+
expand=False,
|
|
256
|
+
)
|
|
257
|
+
)
|
|
258
|
+
console.print(
|
|
259
|
+
" [dim]HOW TO USE[/dim]\n"
|
|
260
|
+
" • Type [bold cyan]/do[/bold cyan] on a new line and press Enter to extract JSON\n"
|
|
261
|
+
" • Press [bold red]Ctrl+C[/bold red] at any time to exit\n"
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
def _read_one_input() -> str:
|
|
265
|
+
console.print("[dim]─────────────────────────────────────[/dim]")
|
|
266
|
+
console.print("[dim]Paste your text below (or Ctrl+C to stop):[/dim]\n")
|
|
267
|
+
lines = []
|
|
268
|
+
while True:
|
|
269
|
+
try:
|
|
270
|
+
line = input()
|
|
271
|
+
except KeyboardInterrupt:
|
|
272
|
+
console.print("\n\n[bold green]Agent signing off.[/bold green] Goodbye!\n")
|
|
273
|
+
sys.exit(0)
|
|
274
|
+
|
|
275
|
+
if line.strip() == "/do":
|
|
276
|
+
break
|
|
277
|
+
lines.append(line)
|
|
278
|
+
return "\n".join(lines)
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
def _print_result(output_str: str, is_error: bool, output_file: str | None):
|
|
282
|
+
console.print()
|
|
283
|
+
if is_error:
|
|
284
|
+
console.print("[bold red]✗ Something went wrong[/bold red]")
|
|
285
|
+
else:
|
|
286
|
+
console.print("[bold green]✓ Extracted JSON[/bold green]")
|
|
287
|
+
|
|
288
|
+
console.print(Syntax(output_str, "json", theme="ansi_dark", word_wrap=True))
|
|
289
|
+
|
|
290
|
+
if CLIPBOARD_AVAILABLE and not is_error:
|
|
291
|
+
try:
|
|
292
|
+
pyperclip.copy(output_str)
|
|
293
|
+
console.print("[dim]✓ Copied to clipboard[/dim]")
|
|
294
|
+
except Exception:
|
|
295
|
+
console.print("[dim]⚠ Clipboard unavailable on this system[/dim]")
|
|
296
|
+
|
|
297
|
+
if output_file:
|
|
298
|
+
try:
|
|
299
|
+
with open(output_file, "w", encoding="utf-8") as f:
|
|
300
|
+
f.write(output_str)
|
|
301
|
+
console.print(f"[dim]✓ Saved to {output_file}[/dim]")
|
|
302
|
+
except Exception as e:
|
|
303
|
+
console.print(f"[bold red]✗ Failed to save output file:[/bold red] {e}")
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
def _execute_processing_pipeline(raw_text: str, client: Groq, model: str, output_file: str | None, status_msg: str):
|
|
307
|
+
"""Centralized extraction engine to prevent code repetition."""
|
|
308
|
+
with console.status(status_msg, spinner="dots"):
|
|
309
|
+
result = extract_json(raw_text, client, model=model)
|
|
310
|
+
|
|
311
|
+
output_str = json.dumps(result, indent=2, ensure_ascii=False)
|
|
312
|
+
is_error = result["summary"].startswith("Could not process input:")
|
|
313
|
+
_print_result(output_str, is_error, output_file)
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
# ── entry point ───────────────────────────────────────────────────────────────
|
|
317
|
+
|
|
318
|
+
def main():
|
|
319
|
+
parser = argparse.ArgumentParser(
|
|
320
|
+
prog="messy2json",
|
|
321
|
+
description="Turn messy text into strict JSON.",
|
|
322
|
+
)
|
|
323
|
+
parser.add_argument("-f", "--file", help="read from a file instead of interactive mode")
|
|
324
|
+
parser.add_argument("-o", "--output", help="also save the JSON result to this file")
|
|
325
|
+
parser.add_argument("--model", help=f"override Groq model (default: {DEFAULT_MODEL})")
|
|
326
|
+
args = parser.parse_args()
|
|
327
|
+
|
|
328
|
+
api_key = get_api_key()
|
|
329
|
+
model = args.model or get_model()
|
|
330
|
+
client = Groq(api_key=api_key)
|
|
331
|
+
|
|
332
|
+
# ── non-interactive mode (Files / Streams) ────────────────────────────────
|
|
333
|
+
if args.file or not sys.stdin.isatty():
|
|
334
|
+
if args.file:
|
|
335
|
+
try:
|
|
336
|
+
raw_text = open(args.file, encoding="utf-8").read()
|
|
337
|
+
except FileNotFoundError:
|
|
338
|
+
console.print(f"[bold red]✗ Error:[/bold red] The file '{args.file}' could not be found.")
|
|
339
|
+
sys.exit(1)
|
|
340
|
+
except Exception as e:
|
|
341
|
+
console.print(f"[bold red]✗ Error reading file:[/bold red] {e}")
|
|
342
|
+
sys.exit(1)
|
|
343
|
+
else:
|
|
344
|
+
raw_text = sys.stdin.read()
|
|
345
|
+
|
|
346
|
+
_execute_processing_pipeline(
|
|
347
|
+
raw_text, client, model, args.output, "[bold yellow]Processing input data...[/bold yellow]"
|
|
348
|
+
)
|
|
349
|
+
return
|
|
350
|
+
|
|
351
|
+
# ── interactive loop mode ─────────────────────────────────────────────────
|
|
352
|
+
show_banner(model)
|
|
353
|
+
try:
|
|
354
|
+
while True:
|
|
355
|
+
raw_text = _read_one_input()
|
|
356
|
+
if not raw_text.strip():
|
|
357
|
+
console.print("[dim]⚠ No text entered — paste something and type /do[/dim]\n")
|
|
358
|
+
continue
|
|
359
|
+
|
|
360
|
+
_execute_processing_pipeline(
|
|
361
|
+
raw_text, client, model, args.output, "[bold yellow] Processing...[/bold yellow]"
|
|
362
|
+
)
|
|
363
|
+
console.print()
|
|
364
|
+
|
|
365
|
+
except KeyboardInterrupt:
|
|
366
|
+
console.print("\n\n[bold green]Agent signing off.[/bold green] Goodbye!\n")
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
if __name__ == "__main__":
|
|
370
|
+
main()
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: messy2json
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Turns messy text (emails, notes, voice-to-text) into structured JSON using Groq LLM.
|
|
5
|
+
Project-URL: Homepage, https://github.com/hamzatahir06/Messy2JSON
|
|
6
|
+
Project-URL: Repository, https://github.com/hamzatahir06/Messy2JSON
|
|
7
|
+
Project-URL: Bug Tracker, https://github.com/hamzatahir06/Messy2JSON/issues
|
|
8
|
+
Requires-Python: >=3.12
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
Requires-Dist: groq>=1.5.0
|
|
11
|
+
Requires-Dist: rich>=13.7.0
|
|
12
|
+
Requires-Dist: pyperclip>=1.8.2
|
|
13
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
14
|
+
|
|
15
|
+
# 🤖 Messy2JSON
|
|
16
|
+
|
|
17
|
+
> **Transform messy, unstructured text into clean, structured JSON using Groq LLMs.**
|
|
18
|
+
|
|
19
|
+
Messy2JSON is a lightweight, cross-platform Python CLI that converts meeting notes, emails, chat logs, and voice-to-text transcripts into structured JSON containing a summary, action items, and deadlines. Built with reliability in mind, it validates AI responses, automatically repairs malformed outputs, and provides a seamless terminal experience.
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## ✨ Features
|
|
24
|
+
|
|
25
|
+
- 🤖 AI-powered information extraction using **Groq LLMs**
|
|
26
|
+
- 🔒 One-time API key setup with live validation
|
|
27
|
+
- 🧠 Automatic JSON self-repair using an AI reflection loop
|
|
28
|
+
- ✅ Strict schema validation for reliable output
|
|
29
|
+
- 📋 Automatic clipboard copy after successful extraction
|
|
30
|
+
- 📂 Read input from files, interactive mode, or Unix pipes
|
|
31
|
+
- 💾 Save structured JSON directly to a file
|
|
32
|
+
- 💻 Cross-platform support (Windows, macOS, Linux)
|
|
33
|
+
- ⚡ Fast, clean terminal interface powered by Rich
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## 📦 Output Format
|
|
38
|
+
|
|
39
|
+
Every input is converted into the following JSON structure:
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
{
|
|
43
|
+
"summary": "A concise summary of the input.",
|
|
44
|
+
"action_items": [
|
|
45
|
+
"Action item 1",
|
|
46
|
+
"Action item 2"
|
|
47
|
+
],
|
|
48
|
+
"deadline": "Mentioned deadline or null"
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## 🚀 Installation
|
|
55
|
+
|
|
56
|
+
### Clone the repository
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
git clone https://github.com/hamzatahir06/Messy2JSON.git
|
|
60
|
+
cd Messy2JSON
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Create a virtual environment
|
|
64
|
+
|
|
65
|
+
**Linux / macOS**
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
python -m venv venv
|
|
69
|
+
source venv/bin/activate
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**Windows**
|
|
73
|
+
|
|
74
|
+
```powershell
|
|
75
|
+
python -m venv venv
|
|
76
|
+
.\venv\Scripts\activate
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Install the package
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
pip install -e .
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
> **PyPI support is coming soon.**
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
pip install messy2json
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## ⚡ Quick Start
|
|
94
|
+
|
|
95
|
+
### Interactive Mode
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
messy2json
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Paste your text, then type:
|
|
102
|
+
|
|
103
|
+
```text
|
|
104
|
+
/do
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
to generate structured JSON.
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
### Read from a File
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
messy2json -f meeting_notes.txt
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
### Read from Standard Input
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
cat notes.txt | messy2json
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
### Save Output to a File
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
messy2json -f notes.txt -o output.json
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
### Use a Different Model
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
messy2json --model llama-3.3-70b-versatile
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## ⚙️ Configuration
|
|
144
|
+
|
|
145
|
+
During the first run, Messy2JSON securely prompts for your Groq API key, validates it online, and stores it locally using your operating system's standard configuration directory.
|
|
146
|
+
|
|
147
|
+
You can also provide configuration through environment variables.
|
|
148
|
+
|
|
149
|
+
| Variable | Description |
|
|
150
|
+
|----------|-------------|
|
|
151
|
+
| `GROQ_API_KEY` | Your Groq API key |
|
|
152
|
+
| `GROQ_MODEL` | Override the default model |
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## 📁 Project Structure
|
|
157
|
+
|
|
158
|
+
```text
|
|
159
|
+
Messy2JSON/
|
|
160
|
+
│
|
|
161
|
+
├── messy2json/
|
|
162
|
+
│ ├── __init__.py
|
|
163
|
+
│ └── main.py
|
|
164
|
+
│
|
|
165
|
+
├── pyproject.toml
|
|
166
|
+
├── README.md
|
|
167
|
+
└── LICENSE
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## 🛠 Built With
|
|
173
|
+
|
|
174
|
+
- **Python 3.12+**
|
|
175
|
+
- **Groq Python SDK**
|
|
176
|
+
- **Rich**
|
|
177
|
+
- **Pyperclip**
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## 💡 Why Messy2JSON?
|
|
182
|
+
|
|
183
|
+
Unlike basic AI wrappers, Messy2JSON is designed to produce **consistent and dependable JSON**.
|
|
184
|
+
|
|
185
|
+
It includes:
|
|
186
|
+
|
|
187
|
+
- Schema validation
|
|
188
|
+
- Automatic retry and self-correction
|
|
189
|
+
- Live API key verification
|
|
190
|
+
- Cross-platform configuration management
|
|
191
|
+
- Clipboard integration
|
|
192
|
+
- Interactive and non-interactive workflows
|
|
193
|
+
|
|
194
|
+
The goal is simple: **give developers structured output they can immediately use in automation pipelines, scripts, or applications.**
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## 📄 License
|
|
199
|
+
|
|
200
|
+
This project is licensed under the **MIT License**.
|
|
201
|
+
|
|
202
|
+
See the [LICENSE](LICENSE) file for details.
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## ⭐ Support the Project
|
|
207
|
+
|
|
208
|
+
If you find Messy2JSON useful, consider giving the repository a ⭐ on GitHub.
|
|
209
|
+
|
|
210
|
+
It helps others discover the project and motivates future development.
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
**Made with ❤️ by [Hamza Tahir](https://github.com/hamzatahir06)**
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
messy2json/__init__.py
|
|
4
|
+
messy2json/main.py
|
|
5
|
+
messy2json.egg-info/PKG-INFO
|
|
6
|
+
messy2json.egg-info/SOURCES.txt
|
|
7
|
+
messy2json.egg-info/dependency_links.txt
|
|
8
|
+
messy2json.egg-info/entry_points.txt
|
|
9
|
+
messy2json.egg-info/requires.txt
|
|
10
|
+
messy2json.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
messy2json
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "messy2json"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Turns messy text (emails, notes, voice-to-text) into structured JSON using Groq LLM."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.12"
|
|
11
|
+
dependencies = [
|
|
12
|
+
"groq>=1.5.0",
|
|
13
|
+
"rich>=13.7.0",
|
|
14
|
+
"pyperclip>=1.8.2",
|
|
15
|
+
"python-dotenv>=1.0.0"
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
[project.scripts]
|
|
19
|
+
messy2json = "messy2json.main:main"
|
|
20
|
+
|
|
21
|
+
[tool.setuptools]
|
|
22
|
+
packages = ["messy2json"]
|
|
23
|
+
|
|
24
|
+
[project.urls]
|
|
25
|
+
Homepage = "https://github.com/hamzatahir06/Messy2JSON"
|
|
26
|
+
Repository = "https://github.com/hamzatahir06/Messy2JSON"
|
|
27
|
+
"Bug Tracker" = "https://github.com/hamzatahir06/Messy2JSON/issues"
|