biblemateagent 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.
@@ -0,0 +1,65 @@
1
+ Metadata-Version: 2.4
2
+ Name: biblemateagent
3
+ Version: 0.1.0
4
+ Summary: BibleMate AI - Automate Your Bible Study; A headless version of BibleMate AI Agent Mode
5
+ Home-page: https://biblemate.ai
6
+ Author: Eliran Wong
7
+ Author-email: support@marvel.bible
8
+ License: GNU General Public License (GPL)
9
+ Project-URL: Source, https://github.com/eliranwong/biblemateagent
10
+ Project-URL: Tracker, https://github.com/eliranwong/biblemateagent/issues
11
+ Project-URL: Documentation, https://github.com/eliranwong/biblemateagent/wiki
12
+ Project-URL: Funding, https://www.paypal.me/MarvelBible
13
+ Keywords: mcp agent biblemate ai anthropic azure chatgpt cohere deepseek genai github googleai groq llamacpp mistral ollama openai vertexai xai
14
+ Classifier: Development Status :: 5 - Production/Stable
15
+ Classifier: Intended Audience :: End Users/Desktop
16
+ Classifier: Topic :: Utilities
17
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
18
+ Classifier: Topic :: Software Development :: Build Tools
19
+ Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Requires-Python: >=3.10, <3.13
24
+ Requires-Dist: biblemateweb>=0.3.56
25
+ Provides-Extra: genai
26
+ Requires-Dist: google-genai>=1.46.0; extra == "genai"
27
+ Dynamic: author
28
+ Dynamic: author-email
29
+ Dynamic: classifier
30
+ Dynamic: description
31
+ Dynamic: home-page
32
+ Dynamic: keywords
33
+ Dynamic: license
34
+ Dynamic: project-url
35
+ Dynamic: provides-extra
36
+ Dynamic: requires-dist
37
+ Dynamic: requires-python
38
+ Dynamic: summary
39
+
40
+ # biblemateagent
41
+ A headless version of BibleMate AI Agent Mode
42
+
43
+ ## Installation
44
+
45
+ > pip install biblemateagent
46
+
47
+ ## Set up data
48
+
49
+ > biblematedata
50
+
51
+ ## Run BibleMate Agent
52
+
53
+ > biblemateagent "Your Bible Study Request"
54
+
55
+ or
56
+
57
+ > bibleagent "Your Bible Study Request"
58
+
59
+ ## Help
60
+
61
+ > biblemateagent -h
62
+
63
+ or
64
+
65
+ > bibleagent -h
@@ -0,0 +1,26 @@
1
+ # biblemateagent
2
+ A headless version of BibleMate AI Agent Mode
3
+
4
+ ## Installation
5
+
6
+ > pip install biblemateagent
7
+
8
+ ## Set up data
9
+
10
+ > biblematedata
11
+
12
+ ## Run BibleMate Agent
13
+
14
+ > biblemateagent "Your Bible Study Request"
15
+
16
+ or
17
+
18
+ > bibleagent "Your Bible Study Request"
19
+
20
+ ## Help
21
+
22
+ > biblemateagent -h
23
+
24
+ or
25
+
26
+ > bibleagent -h
@@ -0,0 +1,26 @@
1
+ # biblemateagent
2
+ A headless version of BibleMate AI Agent Mode
3
+
4
+ ## Installation
5
+
6
+ > pip install biblemateagent
7
+
8
+ ## Set up data
9
+
10
+ > biblematedata
11
+
12
+ ## Run BibleMate Agent
13
+
14
+ > biblemateagent "Your Bible Study Request"
15
+
16
+ or
17
+
18
+ > bibleagent "Your Bible Study Request"
19
+
20
+ ## Help
21
+
22
+ > biblemateagent -h
23
+
24
+ or
25
+
26
+ > bibleagent -h
@@ -0,0 +1,269 @@
1
+ import asyncio
2
+ import datetime
3
+ import re
4
+ import os
5
+ import shutil
6
+ import pypandoc
7
+ import traceback
8
+ from copy import deepcopy
9
+
10
+ from biblemateagent.stream import stream_response_headless
11
+ from biblemateweb import BIBLEMATEWEB_APP_DIR, get_translation, DEFAULT_MESSAGES, chapter2verses
12
+ from biblemateweb.mcp_tools.elements import TOOL_ELEMENTS
13
+ from biblemateweb.mcp_tools.tools import TOOLS
14
+ from biblemateweb.mcp_tools.tool_descriptions import TOOL_DESCRIPTIONS
15
+ from biblemateweb.api.api import get_api_content
16
+ from biblemate.core.systems import get_system_tool_instruction, get_system_master_plan, get_system_make_suggestion, get_system_progress, get_system_generate_title
17
+ from agentmake import agentmake, readTextFile, getCurrentDateTime
18
+
19
+ def do_export(content, filename, export_md=True, export_docx=False, output_directory=None):
20
+
21
+ if not os.path.isdir(output_directory):
22
+ os.makedirs(output_directory)
23
+
24
+ if export_md:
25
+ md_filepath = os.path.join(output_directory, f"{filename}.md")
26
+ with open(md_filepath, "w", encoding="utf-8") as f:
27
+ f.write(content)
28
+ print(f"Exported to: {md_filepath}")
29
+
30
+ if export_docx:
31
+ if not shutil.which("pandoc"):
32
+ print("Pandoc is not installed. Skipping DOCX export.")
33
+ return
34
+ try:
35
+ docx_filepath = os.path.join(output_directory, f"{filename}.docx")
36
+ pypandoc.convert_text(content, 'docx', format='md', outputfile=docx_filepath)
37
+ print(f"Exported to: {docx_filepath}")
38
+ except ImportError:
39
+ print("pypandoc not installed. Skipping DOCX export.")
40
+ except Exception as e:
41
+ print(f"Error exporting to DOCX: {e}")
42
+
43
+ async def ai_agent_headless(q="", ui_language="eng", improve_prompt=False, export_md=False, export_docx=False, output_directory=None, cancel_event=None, developer=False, **kwargs):
44
+
45
+ if output_directory is None:
46
+ output_directory = os.getcwd()
47
+
48
+ MESSAGES = None
49
+ MASTER_PLAN = None
50
+ PROGRESS_STATUS = None
51
+ ROUND = 1
52
+ MASTER_USER_REQUEST = q
53
+
54
+ SYSTEM_TOOL_SELECTION = readTextFile(os.path.join(BIBLEMATEWEB_APP_DIR, "mcp_tools", "system_tool_selection_lite.md"))
55
+
56
+ TOOL_INSTRUCTION_PROMPT = """Please transform the following suggestions into clear, precise, and actionable instructions."""
57
+ TOOL_INSTRUCTION_SUFFIX = """
58
+
59
+ # Remember
60
+
61
+ * Provide me with the instructions directly.
62
+ * Do not start your response, like, 'Here are the insturctions ...'
63
+ * Do not ask me if I want to execute the instruction."""
64
+
65
+ MASTER_PLAN_PROMPT_TEMPLATE = """Provide me with the `Preliminary Action Plan` and the `Measurable Outcome` for resolving `My Request`.
66
+
67
+ # Available Tools
68
+
69
+ Available tools are: {available_tools}.
70
+
71
+ {tool_descriptions}
72
+
73
+ # My Request
74
+
75
+ {user_request}"""
76
+
77
+ FINAL_INSTRUCTION = """# Instruction
78
+ Please provide a comprehensive response that resolves my original request, ensuring all previously completed milestones and data points are fully integrated.
79
+
80
+ # Original Request
81
+ """
82
+
83
+ if not q or not q.strip():
84
+ print("Please provide a request.")
85
+ return None
86
+
87
+ timestamp = getCurrentDateTime()
88
+ generated_title = ""
89
+ generated_title_output = agentmake(MASTER_USER_REQUEST, system=get_system_generate_title(), **kwargs)
90
+ if generated_title_output:
91
+ generated_title = generated_title_output[-1].get("content", "").strip().replace("Title: ", "")
92
+ print(f"\n[TITLE] {generated_title}\n")
93
+ study_directory = f"{timestamp}_{generated_title}"
94
+ output_directory = os.path.join(output_directory, study_directory)
95
+ else:
96
+ study_directory = f"{timestamp}_bible_study"
97
+ output_directory = os.path.join(output_directory, study_directory)
98
+
99
+ print(f"\n[REQUEST] {MASTER_USER_REQUEST}\n")
100
+
101
+ MESSAGES = deepcopy(DEFAULT_MESSAGES)
102
+
103
+ if improve_prompt:
104
+ print("\n--- Improving Prompt ---\n")
105
+ user_request = await stream_response_headless(
106
+ MESSAGES, MASTER_USER_REQUEST, cancel_event, system="improve_prompt_2"
107
+ )
108
+ if user_request and user_request.strip() != "[NO_CONTENT]":
109
+ if "```" in user_request:
110
+ MASTER_USER_REQUEST = re.sub(r"^.*?(```improved_prompt|```)(.+?)```.*?$", r"\2", user_request, flags=re.DOTALL).strip()
111
+ else:
112
+ MASTER_USER_REQUEST = user_request.strip()
113
+ print(f"\n[IMPROVED REQUEST] {MASTER_USER_REQUEST}\n")
114
+
115
+ MESSAGES += [
116
+ {"role": "user", "content": MASTER_USER_REQUEST},
117
+ {"role": "assistant", "content": "Let's begin!"},
118
+ ]
119
+
120
+ # Generate master plan
121
+ print("\n--- Generating Study Plan ---\n")
122
+ master_plan_prompt = MASTER_PLAN_PROMPT_TEMPLATE.format(
123
+ available_tools=list(TOOLS.keys()),
124
+ tool_descriptions=TOOL_DESCRIPTIONS,
125
+ user_request=MASTER_USER_REQUEST
126
+ )
127
+
128
+ MASTER_PLAN = await stream_response_headless(
129
+ MESSAGES, master_plan_prompt, cancel_event, system=get_system_master_plan()
130
+ )
131
+
132
+ if not MASTER_PLAN or MASTER_PLAN.strip() == "[NO_CONTENT]":
133
+ print("Failed to generate master plan.")
134
+ return None
135
+
136
+ if export_md or export_docx:
137
+ filename = f"00_request_and_master_plan"
138
+ content = f"# Title\n\n{generated_title}\n\n" if generated_title else ""
139
+ content += f"# Request\n\n{MASTER_USER_REQUEST}\n\n# Master Plan\n\n{MASTER_PLAN}"
140
+ do_export(content, filename, export_md, export_docx, output_directory)
141
+
142
+ PROGRESS_STATUS = "START"
143
+ print("\n--- Finished generating study plan. Beginning rounds. ---\n")
144
+
145
+ try:
146
+ while PROGRESS_STATUS is None or not ("STOP" in PROGRESS_STATUS or re.sub("^[^A-Za-z]*?([A-Za-z]+?)[^A-Za-z]*?$", r"\1", PROGRESS_STATUS).upper() == "STOP"):
147
+ if cancel_event and cancel_event.is_set():
148
+ break
149
+
150
+ print(f"\n### Round {ROUND} ###\n")
151
+
152
+ # suggestion
153
+ print("\n--- Suggestion ---\n")
154
+ system_make_suggestion = get_system_make_suggestion(master_plan=MASTER_PLAN)
155
+ follow_up_prompt = "Please provide me with the next step suggestion, based on the action plan."
156
+
157
+ suggestion = await stream_response_headless(MESSAGES, follow_up_prompt, cancel_event, system=system_make_suggestion)
158
+
159
+ if not suggestion or suggestion.strip() == "[NO_CONTENT]":
160
+ print("\n[No suggestion generated. Stopping.]\n")
161
+ break
162
+
163
+ # tool selection
164
+ print("\n--- Tool Selection ---\n")
165
+ suggested_tools = await stream_response_headless(DEFAULT_MESSAGES, suggestion, cancel_event, system=SYSTEM_TOOL_SELECTION)
166
+
167
+ if not suggested_tools or suggested_tools.strip() == "[NO_CONTENT]":
168
+ suggested_tools_list = ["get_direct_text_response"]
169
+ else:
170
+ try:
171
+ suggested_tools_str = re.sub(r"^.*?(\[.*?\]).*?$", r"\1", suggested_tools, flags=re.DOTALL)
172
+ suggested_tools_list = eval(suggested_tools_str.replace("`", "'")) if suggested_tools_str.startswith("[") and suggested_tools_str.endswith("]") else ["get_direct_text_response"]
173
+ except:
174
+ suggested_tools_list = ["get_direct_text_response"]
175
+
176
+ selected_tool = suggested_tools_list[0] if suggested_tools_list else "get_direct_text_response"
177
+ if not selected_tool in TOOLS:
178
+ selected_tool = "get_direct_text_response"
179
+
180
+ print(f"\n[Selected Tool: {selected_tool}]\n")
181
+
182
+ # tool instruction
183
+ print("\n--- Tool Instruction ---\n")
184
+ selected_tool_description = TOOLS.get(selected_tool, "No description available.")
185
+ tool_instruction_draft = TOOL_INSTRUCTION_PROMPT + "\n\n# Suggestions\n\n"+suggestion+f"\n\n# Tool Description of `{selected_tool}`\n\n"+selected_tool_description+TOOL_INSTRUCTION_SUFFIX
186
+ system_tool_instruction = get_system_tool_instruction(selected_tool, selected_tool_description)
187
+
188
+ user_request = await stream_response_headless(MESSAGES, tool_instruction_draft, cancel_event, system=system_tool_instruction)
189
+
190
+ if not user_request or user_request.strip() == "[NO_CONTENT]":
191
+ print("\n[No tool instruction generated. Stopping.]\n")
192
+ break
193
+
194
+ print("\n--- Agent Execution ---\n")
195
+ answers = None
196
+ try:
197
+ if selected_tool == "get_direct_text_response":
198
+ answers = await stream_response_headless(MESSAGES, user_request, cancel_event, system="auto")
199
+ else:
200
+ element = TOOL_ELEMENTS.get(selected_tool)
201
+ if isinstance(element, str):
202
+ print(f"Loading {selected_tool}...")
203
+ if not selected_tool == "search_the_whole_bible":
204
+ user_req = chapter2verses(user_request)
205
+ else:
206
+ user_req = user_request
207
+ api_query = f"{element}{user_req}"
208
+ answers = await asyncio.to_thread(get_api_content, api_query, ui_language)
209
+ if answers:
210
+ print(answers)
211
+ else:
212
+ answers = "[NO_CONTENT]"
213
+ print(answers)
214
+ elif isinstance(element, dict):
215
+ system = element.pop("system") if "system" in element else None
216
+ answers = await stream_response_headless(MESSAGES, user_request, cancel_event, system=system, **element)
217
+
218
+ except Exception as e:
219
+ answers = f"[{get_translation('Error')}: {str(e)}]"
220
+ print(f"\n{answers}\n")
221
+ if developer:
222
+ traceback.print_exc()
223
+
224
+ if answers and not (answers.strip() == "[NO_CONTENT]" or answers.startswith("[Error:")):
225
+ if export_md or export_docx:
226
+ round_str = f"{ROUND:02}"
227
+ filename = f"{round_str}_{selected_tool}"
228
+ do_export(answers, filename, export_md, export_docx, output_directory)
229
+ MESSAGES += [
230
+ {"role": "user", "content": f"[ROUND {ROUND}]\n\n{user_request}"},
231
+ {"role": "assistant", "content": f"[TOOL] {selected_tool}\n\n[RESPONSE]\n\n{answers}"},
232
+ ]
233
+
234
+ # check progress
235
+ print("\n--- Progress Check ---\n")
236
+ system_progress = get_system_progress(master_plan=MASTER_PLAN)
237
+ follow_up_prompt="Please decide either to `CONTINUE` or `STOP` the process."
238
+ PROGRESS_STATUS = await stream_response_headless(MESSAGES, follow_up_prompt, cancel_event, system=system_progress)
239
+
240
+ if not PROGRESS_STATUS or PROGRESS_STATUS.strip() == "[NO_CONTENT]":
241
+ MESSAGES = MESSAGES[:-2]
242
+ break
243
+
244
+ ROUND += 1
245
+
246
+ print("\n---\n")
247
+ print("\nWrapping up...\n")
248
+ print("\n--- Final Report ---\n")
249
+ system_report = "write_final_answer"
250
+ follow_up_prompt=f"""{FINAL_INSTRUCTION}{MASTER_USER_REQUEST}"""
251
+ report = await stream_response_headless(MESSAGES, follow_up_prompt, cancel_event, system=system_report)
252
+
253
+ if report and report.strip() != "[NO_CONTENT]":
254
+ if export_md or export_docx:
255
+ round_str = f"{ROUND:02}"
256
+ filename = f"{round_str}_final_report"
257
+ do_export(report, filename, export_md, export_docx, output_directory)
258
+ MESSAGES += [
259
+ {"role": "user", "content": "[FINAL] Please provide a comprehensive response that resolves my original request, ensuring all previously completed milestones and data points are fully integrated."},
260
+ {"role": "assistant", "content": f"[REPORT]\n\n{report}"},
261
+ ]
262
+ print("\n--- Finished successfully ---\n")
263
+
264
+ return MESSAGES
265
+
266
+ except Exception as e:
267
+ print(f"\nError: {e}\n")
268
+ # traceback.print_exc()
269
+ return None
File without changes
@@ -0,0 +1,20 @@
1
+ import asyncio, argparse
2
+ from biblemateagent.agent import ai_agent_headless
3
+
4
+ parser = argparse.ArgumentParser(description = f"""BibleMate AI Agent""")
5
+ parser.add_argument("default", nargs="*", default=None, help="user query")
6
+ parser.add_argument("-l", "--language", action="store", dest="language", help="language option; `eng` by defatul; set this option to `tc` or `sc` to override")
7
+ parser.add_argument("-t", "--token", action="store", dest="token", help=f"custom token to get acccess to custom data")
8
+ parser.add_argument("-u", "--url", action="store", dest="url", help=f"custom token to get acccess to custom data")
9
+ args = parser.parse_args()
10
+
11
+ async def main_async():
12
+ print("Starting BibleMate AI Agent...")
13
+ await ai_agent_headless(q=" ".join(args.default))
14
+ print("Finished")
15
+
16
+ def main():
17
+ asyncio.run(main_async())
18
+
19
+ if __name__ == "__main__":
20
+ main()
@@ -0,0 +1 @@
1
+ biblemateagent
@@ -0,0 +1 @@
1
+ biblemateweb>=0.3.56
@@ -0,0 +1,125 @@
1
+ import asyncio
2
+ import os
3
+ from agentmake import agentmake, DEFAULT_AI_BACKEND, unpack_instruction_content, unpack_system_content
4
+ from agentmake.utils.text_wrapper import get_stream_event_text
5
+ from agentmake.utils.read_assistant_response import is_openai_style
6
+ from biblemateweb import config, DEFAULT_MESSAGES
7
+
8
+ async def stream_response_headless(messages, user_request, cancel_event=None, system=None, **kwargs):
9
+ def get_next_chunk(iterator):
10
+ """
11
+ Runs in a separate thread.
12
+ Returns the next item, or None if the iterator is exhausted.
13
+ """
14
+ try:
15
+ return next(iterator)
16
+ except StopIteration:
17
+ return None
18
+ except Exception as e:
19
+ return e # Return the error to be handled in the main loop
20
+
21
+ if "instruction" in kwargs:
22
+ instruction_content = kwargs.pop("instruction")
23
+ instruction_content = unpack_instruction_content(instruction_content)
24
+ # refine user request
25
+ user_request = instruction_content + "\n" + user_request
26
+
27
+ if system == "auto":
28
+ system = await stream_response_headless(DEFAULT_MESSAGES, user_request, cancel_event, system="bible/create_agent", **kwargs)
29
+ if not system or system.strip() == "[NO_CONTENT]":
30
+ return None
31
+ else:
32
+ # refine response
33
+ system = system.replace("should:", "should:\n")
34
+ system = system.replace("examples:", "examples:\n")
35
+ if system.startswith("```agent\n"):
36
+ system = system[9:]
37
+ if system.endswith("```"):
38
+ system = system[:-3].strip()
39
+ elif system is not None:
40
+ system_content = unpack_system_content(system)
41
+ system = None
42
+ # refine user request
43
+ user_request = f"""---
44
+
45
+ START OF YOUR NEW ROLE
46
+
47
+ ---
48
+
49
+ {system_content}
50
+
51
+ ---
52
+
53
+ START OF MY REQUEST
54
+
55
+ ---
56
+
57
+ {user_request}"""
58
+
59
+ # Print loading text
60
+ print("Loading...", end="\r", flush=True)
61
+ await asyncio.sleep(0)
62
+
63
+ backend = kwargs.pop("backend", getattr(config, "ai_backend", "") if getattr(config, "ai_backend", "") else DEFAULT_AI_BACKEND)
64
+ api_key = kwargs.pop("api_key", os.getenv("API_KEY", ""))
65
+ api_endpoint = kwargs.pop("api_endpoint", os.getenv("API_ENDPOINT", ""))
66
+ model = kwargs.pop("model", os.getenv("AI_MODEL", ""))
67
+ max_tokens = kwargs.pop("max_tokens", None)
68
+ temperature = kwargs.pop("temperature", None)
69
+
70
+ disable_local_api_endpoint = getattr(config, "disable_local_api_endpoint", True)
71
+ if disable_local_api_endpoint and (api_endpoint.strip().lower().startswith("http://localhost") or api_endpoint.strip().lower().startswith("http://127.0.0.1")):
72
+ api_endpoint = ""
73
+
74
+ # run completion
75
+ text_chunks = ""
76
+ completion = await asyncio.to_thread(
77
+ agentmake,
78
+ messages,
79
+ system=system,
80
+ backend=backend.strip() if api_key.strip() and not backend.strip() == "default" else config.ai_backend if getattr(config, "ai_backend", "") else DEFAULT_AI_BACKEND,
81
+ model=model.strip() if api_key.strip() and model.strip() and not backend.strip() == "default" else None,
82
+ api_key=api_key.strip() if api_key.strip() and not backend.strip() == "default" else None,
83
+ api_endpoint=api_endpoint.strip() if api_key.strip() and api_endpoint.strip() and not backend.strip() == "default" else None,
84
+ max_tokens=int(max_tokens) if api_key.strip() and max_tokens and not backend.strip() == "default" else None,
85
+ temperature=float(temperature) if api_key.strip() and temperature and not backend.strip() == "default" else None,
86
+ follow_up_prompt=user_request,
87
+ stream=True,
88
+ print_on_terminal=False,
89
+ stream_events_only=True,
90
+ **kwargs,
91
+ )
92
+
93
+ print("Running... ", end="\r", flush=True)
94
+
95
+ try:
96
+ while cancel_event is None or not cancel_event.is_set():
97
+ event = await asyncio.to_thread(get_next_chunk, completion)
98
+
99
+ if event is None:
100
+ break
101
+ elif isinstance(event, Exception):
102
+ print(f"\nStream interrupted: {str(event)}")
103
+ break
104
+
105
+ actual_backend = backend.strip() if api_key.strip() and not backend.strip() == "default" else config.ai_backend if getattr(config, "ai_backend", "") else DEFAULT_AI_BACKEND
106
+ if text_chunk := get_stream_event_text(event, openai_style=is_openai_style(actual_backend)):
107
+ text_chunks += text_chunk
108
+ print(text_chunk, end="", flush=True)
109
+ await asyncio.sleep(0)
110
+
111
+ if cancel_event is not None and cancel_event.is_set():
112
+ print("\n[Cancelled!]")
113
+ else:
114
+ print() # Print newline when done
115
+
116
+ except Exception as e:
117
+ print(f"\n[Error: {str(e)}]")
118
+ if cancel_event is not None:
119
+ cancel_event.set()
120
+
121
+ if cancel_event is not None and cancel_event.is_set():
122
+ cancel_event = None
123
+ return None
124
+
125
+ return text_chunks.replace(" ", " ").replace("‑", "-")
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,65 @@
1
+ Metadata-Version: 2.4
2
+ Name: biblemateagent
3
+ Version: 0.1.0
4
+ Summary: BibleMate AI - Automate Your Bible Study; A headless version of BibleMate AI Agent Mode
5
+ Home-page: https://biblemate.ai
6
+ Author: Eliran Wong
7
+ Author-email: support@marvel.bible
8
+ License: GNU General Public License (GPL)
9
+ Project-URL: Source, https://github.com/eliranwong/biblemateagent
10
+ Project-URL: Tracker, https://github.com/eliranwong/biblemateagent/issues
11
+ Project-URL: Documentation, https://github.com/eliranwong/biblemateagent/wiki
12
+ Project-URL: Funding, https://www.paypal.me/MarvelBible
13
+ Keywords: mcp agent biblemate ai anthropic azure chatgpt cohere deepseek genai github googleai groq llamacpp mistral ollama openai vertexai xai
14
+ Classifier: Development Status :: 5 - Production/Stable
15
+ Classifier: Intended Audience :: End Users/Desktop
16
+ Classifier: Topic :: Utilities
17
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
18
+ Classifier: Topic :: Software Development :: Build Tools
19
+ Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Requires-Python: >=3.10, <3.13
24
+ Requires-Dist: biblemateweb>=0.3.56
25
+ Provides-Extra: genai
26
+ Requires-Dist: google-genai>=1.46.0; extra == "genai"
27
+ Dynamic: author
28
+ Dynamic: author-email
29
+ Dynamic: classifier
30
+ Dynamic: description
31
+ Dynamic: home-page
32
+ Dynamic: keywords
33
+ Dynamic: license
34
+ Dynamic: project-url
35
+ Dynamic: provides-extra
36
+ Dynamic: requires-dist
37
+ Dynamic: requires-python
38
+ Dynamic: summary
39
+
40
+ # biblemateagent
41
+ A headless version of BibleMate AI Agent Mode
42
+
43
+ ## Installation
44
+
45
+ > pip install biblemateagent
46
+
47
+ ## Set up data
48
+
49
+ > biblematedata
50
+
51
+ ## Run BibleMate Agent
52
+
53
+ > biblemateagent "Your Bible Study Request"
54
+
55
+ or
56
+
57
+ > bibleagent "Your Bible Study Request"
58
+
59
+ ## Help
60
+
61
+ > biblemateagent -h
62
+
63
+ or
64
+
65
+ > bibleagent -h
@@ -0,0 +1,16 @@
1
+ README.md
2
+ setup.py
3
+ biblemateagent/README.md
4
+ biblemateagent/agent.py
5
+ biblemateagent/config.py
6
+ biblemateagent/main.py
7
+ biblemateagent/package_name.txt
8
+ biblemateagent/requirements.txt
9
+ biblemateagent/stream.py
10
+ biblemateagent/version.txt
11
+ biblemateagent.egg-info/PKG-INFO
12
+ biblemateagent.egg-info/SOURCES.txt
13
+ biblemateagent.egg-info/dependency_links.txt
14
+ biblemateagent.egg-info/entry_points.txt
15
+ biblemateagent.egg-info/requires.txt
16
+ biblemateagent.egg-info/top_level.txt
@@ -0,0 +1,4 @@
1
+ [console_scripts]
2
+ bibleagent = biblemateagent.main:main
3
+ biblemateagent = biblemateagent.main:main
4
+ bmagent = biblemateagent.main:main
@@ -0,0 +1,4 @@
1
+ biblemateweb>=0.3.56
2
+
3
+ [genai]
4
+ google-genai>=1.46.0
@@ -0,0 +1 @@
1
+ biblemateagent
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,96 @@
1
+ from setuptools import setup
2
+ from setuptools.command.install import install
3
+ import os, shutil, platform, sys
4
+
5
+ version = "0.1.0"
6
+ with open(os.path.join("biblemateagent", "version.txt"), "w", encoding="utf-8") as fileObj:
7
+ fileObj.write(version)
8
+
9
+ # package name
10
+ package_name_0 = "package_name.txt"
11
+ with open(package_name_0, "r", encoding="utf-8") as fileObj:
12
+ package = fileObj.read()
13
+ package_name_1 = os.path.join(package, "package_name.txt") # package readme
14
+ shutil.copy(package_name_0, package_name_1)
15
+
16
+ # update package readme
17
+ latest_readme = os.path.join("README.md") # github repository readme
18
+ package_readme = os.path.join(package, "README.md") # package readme
19
+ shutil.copy(latest_readme, package_readme)
20
+ with open(package_readme, "r", encoding="utf-8") as fileObj:
21
+ long_description = fileObj.read()
22
+
23
+ # get required packages
24
+ install_requires = []
25
+ with open(os.path.join(package, "requirements.txt"), "r") as fileObj:
26
+ for line in fileObj.readlines():
27
+ mod = line.strip()
28
+ if mod:
29
+ install_requires.append(mod)
30
+
31
+ # make sure config.py is empty
32
+ open(os.path.join(package, "config.py"), "w").close()
33
+
34
+ # https://packaging.python.org/en/latest/guides/distributing-packages-using-setuptools/
35
+ setup(
36
+ name=package,
37
+ version=version,
38
+ python_requires=">=3.10, <3.13",
39
+ description=f"BibleMate AI - Automate Your Bible Study; A headless version of BibleMate AI Agent Mode",
40
+ long_description=long_description,
41
+ author="Eliran Wong",
42
+ author_email="support@marvel.bible",
43
+ packages=[
44
+ package,
45
+ ],
46
+ package_data={
47
+ package: ["*.*"],
48
+ },
49
+ license="GNU General Public License (GPL)",
50
+ install_requires=install_requires,
51
+ extras_require={
52
+ 'genai': ["google-genai>=1.46.0"], # Dependencies for running Vertex AI
53
+ },
54
+ entry_points={
55
+ "console_scripts": [
56
+ f"bmagent={package}.main:main",
57
+ f"biblemateagent={package}.main:main",
58
+ f"bibleagent={package}.main:main",
59
+ ],
60
+ },
61
+ keywords="mcp agent biblemate ai anthropic azure chatgpt cohere deepseek genai github googleai groq llamacpp mistral ollama openai vertexai xai",
62
+ url="https://biblemate.ai",
63
+ project_urls={
64
+ "Source": "https://github.com/eliranwong/biblemateagent",
65
+ "Tracker": "https://github.com/eliranwong/biblemateagent/issues",
66
+ "Documentation": "https://github.com/eliranwong/biblemateagent/wiki",
67
+ "Funding": "https://www.paypal.me/MarvelBible",
68
+ },
69
+ classifiers=[
70
+ # Reference: https://pypi.org/classifiers/
71
+
72
+ # How mature is this project? Common values are
73
+ # 3 - Alpha
74
+ # 4 - Beta
75
+ # 5 - Production/Stable
76
+ 'Development Status :: 5 - Production/Stable',
77
+
78
+ # Indicate who your project is intended for
79
+ 'Intended Audience :: End Users/Desktop',
80
+ 'Topic :: Utilities',
81
+ 'Topic :: Scientific/Engineering :: Artificial Intelligence',
82
+ 'Topic :: Software Development :: Build Tools',
83
+
84
+ # Pick your license as you wish (should match "license" above)
85
+ 'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)',
86
+
87
+ # Specify the Python versions you support here. In particular, ensure
88
+ # that you indicate whether you support Python 2, Python 3 or both.
89
+ #'Programming Language :: Python :: 3.8',
90
+ #'Programming Language :: Python :: 3.9',
91
+ # currently, fastmcp supports 3.10-3.12
92
+ 'Programming Language :: Python :: 3.10',
93
+ 'Programming Language :: Python :: 3.11',
94
+ 'Programming Language :: Python :: 3.12',
95
+ ],
96
+ )