npcpy 1.2.27__tar.gz → 1.2.28__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.
- {npcpy-1.2.27/npcpy.egg-info → npcpy-1.2.28}/PKG-INFO +3 -3
- {npcpy-1.2.27 → npcpy-1.2.28}/README.md +2 -2
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/npc_compiler.py +23 -24
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/serve.py +96 -82
- {npcpy-1.2.27 → npcpy-1.2.28/npcpy.egg-info}/PKG-INFO +3 -3
- {npcpy-1.2.27 → npcpy-1.2.28}/setup.py +1 -1
- {npcpy-1.2.27 → npcpy-1.2.28}/LICENSE +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/MANIFEST.in +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/__init__.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/data/__init__.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/data/audio.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/data/data_models.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/data/image.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/data/load.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/data/text.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/data/video.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/data/web.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/ft/__init__.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/ft/diff.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/ft/ge.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/ft/memory_trainer.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/ft/model_ensembler.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/ft/rl.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/ft/sft.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/ft/usft.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/gen/__init__.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/gen/audio_gen.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/gen/embeddings.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/gen/image_gen.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/gen/response.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/gen/video_gen.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/llm_funcs.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/main.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/memory/__init__.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/memory/command_history.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/memory/kg_vis.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/memory/knowledge_graph.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/memory/memory_processor.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/memory/search.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/mix/__init__.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/mix/debate.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/npc_sysenv.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/npcs.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/sql/__init__.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/sql/ai_function_tools.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/sql/database_ai_adapters.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/sql/database_ai_functions.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/sql/model_runner.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/sql/npcsql.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/sql/sql_model_compiler.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/tools.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/work/__init__.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/work/desktop.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/work/plan.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/work/trigger.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy.egg-info/SOURCES.txt +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy.egg-info/dependency_links.txt +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy.egg-info/requires.txt +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/npcpy.egg-info/top_level.txt +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/setup.cfg +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/tests/test_audio.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/tests/test_command_history.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/tests/test_image.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/tests/test_llm_funcs.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/tests/test_load.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/tests/test_npc_compiler.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/tests/test_npcsql.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/tests/test_response.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/tests/test_serve.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/tests/test_text.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/tests/test_tools.py +0 -0
- {npcpy-1.2.27 → npcpy-1.2.28}/tests/test_web.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: npcpy
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.28
|
|
4
4
|
Summary: npcpy is the premier open-source library for integrating LLMs and Agents into python systems.
|
|
5
5
|
Home-page: https://github.com/NPC-Worldwide/npcpy
|
|
6
6
|
Author: Christopher Agostino
|
|
@@ -330,7 +330,7 @@ Users are not required to pass agents to get_llm_response, so you can work with
|
|
|
330
330
|
```python
|
|
331
331
|
from npcpy.npc_sysenv import print_and_process_stream
|
|
332
332
|
from npcpy.llm_funcs import get_llm_response
|
|
333
|
-
response = get_llm_response("When did the united states government begin sending advisors to vietnam?", model='
|
|
333
|
+
response = get_llm_response("When did the united states government begin sending advisors to vietnam?", model='qwen3:latest', provider='ollama', stream = True)
|
|
334
334
|
|
|
335
335
|
full_response = print_and_process_stream(response['response'], 'llama3.2', 'ollama')
|
|
336
336
|
```
|
|
@@ -338,7 +338,7 @@ Return structured outputs by specifying `format='json'` or passing a Pydantic sc
|
|
|
338
338
|
|
|
339
339
|
```python
|
|
340
340
|
from npcpy.llm_funcs import get_llm_response
|
|
341
|
-
response = get_llm_response("What is the sentiment of the american people towards the repeal of Roe v Wade? Return a json object with `sentiment` as the key and a float value from -1 to 1 as the value", model='
|
|
341
|
+
response = get_llm_response("What is the sentiment of the american people towards the repeal of Roe v Wade? Return a json object with `sentiment` as the key and a float value from -1 to 1 as the value", model='claude-4-5-haiku-latest', provider='deepseek', format='json')
|
|
342
342
|
|
|
343
343
|
print(response['response'])
|
|
344
344
|
```
|
|
@@ -234,7 +234,7 @@ Users are not required to pass agents to get_llm_response, so you can work with
|
|
|
234
234
|
```python
|
|
235
235
|
from npcpy.npc_sysenv import print_and_process_stream
|
|
236
236
|
from npcpy.llm_funcs import get_llm_response
|
|
237
|
-
response = get_llm_response("When did the united states government begin sending advisors to vietnam?", model='
|
|
237
|
+
response = get_llm_response("When did the united states government begin sending advisors to vietnam?", model='qwen3:latest', provider='ollama', stream = True)
|
|
238
238
|
|
|
239
239
|
full_response = print_and_process_stream(response['response'], 'llama3.2', 'ollama')
|
|
240
240
|
```
|
|
@@ -242,7 +242,7 @@ Return structured outputs by specifying `format='json'` or passing a Pydantic sc
|
|
|
242
242
|
|
|
243
243
|
```python
|
|
244
244
|
from npcpy.llm_funcs import get_llm_response
|
|
245
|
-
response = get_llm_response("What is the sentiment of the american people towards the repeal of Roe v Wade? Return a json object with `sentiment` as the key and a float value from -1 to 1 as the value", model='
|
|
245
|
+
response = get_llm_response("What is the sentiment of the american people towards the repeal of Roe v Wade? Return a json object with `sentiment` as the key and a float value from -1 to 1 as the value", model='claude-4-5-haiku-latest', provider='deepseek', format='json')
|
|
246
246
|
|
|
247
247
|
print(response['response'])
|
|
248
248
|
```
|
|
@@ -477,23 +477,23 @@ output = {mcp_tool.__module__}.{name}(
|
|
|
477
477
|
except:
|
|
478
478
|
pass
|
|
479
479
|
|
|
480
|
-
|
|
481
480
|
def load_jinxs_from_directory(directory):
|
|
482
|
-
"""Load all jinxs from a directory"""
|
|
481
|
+
"""Load all jinxs from a directory recursively"""
|
|
483
482
|
jinxs = []
|
|
484
483
|
directory = os.path.expanduser(directory)
|
|
485
484
|
|
|
486
485
|
if not os.path.exists(directory):
|
|
487
486
|
return jinxs
|
|
488
|
-
|
|
489
|
-
for
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
487
|
+
|
|
488
|
+
for root, dirs, files in os.walk(directory):
|
|
489
|
+
for filename in files:
|
|
490
|
+
if filename.endswith(".jinx"):
|
|
491
|
+
try:
|
|
492
|
+
jinx_path = os.path.join(root, filename)
|
|
493
|
+
jinx = Jinx(jinx_path=jinx_path)
|
|
494
|
+
jinxs.append(jinx)
|
|
495
|
+
except Exception as e:
|
|
496
|
+
print(f"Error loading jinx {filename}: {e}")
|
|
497
497
|
|
|
498
498
|
return jinxs
|
|
499
499
|
|
|
@@ -693,7 +693,8 @@ class NPC:
|
|
|
693
693
|
self.jinxs_directory = os.path.expanduser('~/.npcsh/npc_team/jinxs/')
|
|
694
694
|
else:
|
|
695
695
|
self.jinxs_directory = None
|
|
696
|
-
self.npc_directory = None
|
|
696
|
+
self.npc_directory = None
|
|
697
|
+
|
|
697
698
|
self.team = team
|
|
698
699
|
if tools is not None:
|
|
699
700
|
tools_schema, tool_map = auto_tools(tools)
|
|
@@ -1057,18 +1058,16 @@ class NPC:
|
|
|
1057
1058
|
"""Load and process NPC-specific jinxs"""
|
|
1058
1059
|
npc_jinxs = []
|
|
1059
1060
|
|
|
1060
|
-
if self.jinxs_directory is None:
|
|
1061
|
-
self.jinxs_dict = {}
|
|
1062
|
-
return None
|
|
1063
|
-
|
|
1064
1061
|
if jinxs == "*":
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1062
|
+
if self.team and hasattr(self.team, 'jinxs_dict'):
|
|
1063
|
+
for jinx in self.team.jinxs_dict.values():
|
|
1064
|
+
npc_jinxs.append(jinx)
|
|
1065
|
+
elif self.use_global_jinxs or (hasattr(self, 'jinxs_directory') and self.jinxs_directory):
|
|
1066
|
+
jinxs_dir = self.jinxs_directory or os.path.expanduser('~/.npcsh/npc_team/jinxs/')
|
|
1067
|
+
if os.path.exists(jinxs_dir):
|
|
1068
|
+
npc_jinxs.extend(load_jinxs_from_directory(jinxs_dir))
|
|
1069
1069
|
|
|
1070
1070
|
self.jinxs_dict = {jinx.jinx_name: jinx for jinx in npc_jinxs}
|
|
1071
|
-
|
|
1072
1071
|
return npc_jinxs
|
|
1073
1072
|
|
|
1074
1073
|
for jinx in jinxs:
|
|
@@ -1076,13 +1075,13 @@ class NPC:
|
|
|
1076
1075
|
npc_jinxs.append(jinx)
|
|
1077
1076
|
elif isinstance(jinx, dict):
|
|
1078
1077
|
npc_jinxs.append(Jinx(jinx_data=jinx))
|
|
1079
|
-
|
|
1078
|
+
elif isinstance(jinx, str):
|
|
1080
1079
|
jinx_path = None
|
|
1081
1080
|
jinx_name = jinx
|
|
1082
1081
|
if not jinx_name.endswith(".jinx"):
|
|
1083
1082
|
jinx_name += ".jinx"
|
|
1084
1083
|
|
|
1085
|
-
if hasattr(self, 'jinxs_directory') and os.path.exists(self.jinxs_directory):
|
|
1084
|
+
if hasattr(self, 'jinxs_directory') and self.jinxs_directory and os.path.exists(self.jinxs_directory):
|
|
1086
1085
|
candidate_path = os.path.join(self.jinxs_directory, jinx_name)
|
|
1087
1086
|
if os.path.exists(candidate_path):
|
|
1088
1087
|
jinx_path = candidate_path
|
|
@@ -1092,8 +1091,8 @@ class NPC:
|
|
|
1092
1091
|
npc_jinxs.append(jinx_obj)
|
|
1093
1092
|
|
|
1094
1093
|
self.jinxs_dict = {jinx.jinx_name: jinx for jinx in npc_jinxs}
|
|
1094
|
+
print(npc_jinxs)
|
|
1095
1095
|
return npc_jinxs
|
|
1096
|
-
|
|
1097
1096
|
def get_llm_response(self,
|
|
1098
1097
|
request,
|
|
1099
1098
|
jinxs=None,
|
|
@@ -502,56 +502,73 @@ def get_global_settings():
|
|
|
502
502
|
except Exception as e:
|
|
503
503
|
print(f"Error in get_global_settings: {str(e)}")
|
|
504
504
|
return jsonify({"error": str(e)}), 500
|
|
505
|
-
|
|
505
|
+
def _get_jinx_files_recursively(directory):
|
|
506
|
+
"""Helper to recursively find all .jinx file paths."""
|
|
507
|
+
jinx_paths = []
|
|
508
|
+
if os.path.exists(directory):
|
|
509
|
+
for root, _, files in os.walk(directory):
|
|
510
|
+
for filename in files:
|
|
511
|
+
if filename.endswith(".jinx"):
|
|
512
|
+
jinx_paths.append(os.path.join(root, filename))
|
|
513
|
+
return jinx_paths
|
|
506
514
|
|
|
507
515
|
@app.route("/api/jinxs/available", methods=["GET"])
|
|
508
516
|
def get_available_jinxs():
|
|
509
|
-
"""
|
|
510
|
-
Get all available jinxs for a given NPC and/or team.
|
|
511
|
-
Returns a list of jinx names that can be executed.
|
|
512
|
-
"""
|
|
513
517
|
try:
|
|
514
518
|
current_path = request.args.get('currentPath')
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
jinx_names = set() # Use set to avoid duplicates
|
|
518
|
-
|
|
519
|
-
# Get team jinxs from project directory
|
|
519
|
+
jinx_names = set()
|
|
520
|
+
|
|
520
521
|
if current_path:
|
|
521
522
|
team_jinxs_dir = os.path.join(current_path, 'npc_team', 'jinxs')
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
# Get global jinxs
|
|
523
|
+
jinx_paths = _get_jinx_files_recursively(team_jinxs_dir)
|
|
524
|
+
for path in jinx_paths:
|
|
525
|
+
jinx_names.add(os.path.basename(path)[:-5])
|
|
526
|
+
|
|
528
527
|
global_jinxs_dir = os.path.expanduser('~/.npcsh/npc_team/jinxs')
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
# Get NPC-specific jinxs if NPC is specified
|
|
535
|
-
if npc_name:
|
|
536
|
-
# Try to load the NPC and get its jinxs
|
|
537
|
-
db_conn = get_db_connection()
|
|
538
|
-
npc_object = load_npc_by_name_and_source(npc_name, 'project', db_conn, current_path)
|
|
539
|
-
if not npc_object:
|
|
540
|
-
npc_object = load_npc_by_name_and_source(npc_name, 'global', db_conn)
|
|
541
|
-
|
|
542
|
-
if npc_object and hasattr(npc_object, 'jinxs_dict') and npc_object.jinxs_dict:
|
|
543
|
-
jinx_names.update(npc_object.jinxs_dict.keys())
|
|
544
|
-
|
|
545
|
-
return jsonify({
|
|
546
|
-
'jinxs': sorted(list(jinx_names)),
|
|
547
|
-
'error': None
|
|
548
|
-
})
|
|
549
|
-
|
|
528
|
+
jinx_paths = _get_jinx_files_recursively(global_jinxs_dir)
|
|
529
|
+
for path in jinx_paths:
|
|
530
|
+
jinx_names.add(os.path.basename(path)[:-5])
|
|
531
|
+
|
|
532
|
+
return jsonify({'jinxs': sorted(list(jinx_names)), 'error': None})
|
|
550
533
|
except Exception as e:
|
|
551
534
|
print(f"Error getting available jinxs: {str(e)}")
|
|
552
535
|
traceback.print_exc()
|
|
553
536
|
return jsonify({'jinxs': [], 'error': str(e)}), 500
|
|
554
537
|
|
|
538
|
+
@app.route("/api/jinxs/global", methods=["GET"])
|
|
539
|
+
def get_global_jinxs():
|
|
540
|
+
jinxs_dir = os.path.join(os.path.expanduser("~"), ".npcsh", "npc_team", "jinxs")
|
|
541
|
+
jinx_paths = _get_jinx_files_recursively(jinxs_dir)
|
|
542
|
+
jinxs = []
|
|
543
|
+
for path in jinx_paths:
|
|
544
|
+
try:
|
|
545
|
+
with open(path, "r") as f:
|
|
546
|
+
jinx_data = yaml.safe_load(f)
|
|
547
|
+
jinxs.append(jinx_data)
|
|
548
|
+
except Exception as e:
|
|
549
|
+
print(f"Error loading global jinx {path}: {e}")
|
|
550
|
+
return jsonify({"jinxs": jinxs})
|
|
551
|
+
|
|
552
|
+
@app.route("/api/jinxs/project", methods=["GET"])
|
|
553
|
+
def get_project_jinxs():
|
|
554
|
+
current_path = request.args.get("currentPath")
|
|
555
|
+
if not current_path:
|
|
556
|
+
return jsonify({"jinxs": []})
|
|
557
|
+
|
|
558
|
+
if not current_path.endswith("npc_team"):
|
|
559
|
+
current_path = os.path.join(current_path, "npc_team")
|
|
560
|
+
|
|
561
|
+
jinxs_dir = os.path.join(current_path, "jinxs")
|
|
562
|
+
jinx_paths = _get_jinx_files_recursively(jinxs_dir)
|
|
563
|
+
jinxs = []
|
|
564
|
+
for path in jinx_paths:
|
|
565
|
+
try:
|
|
566
|
+
with open(path, "r") as f:
|
|
567
|
+
jinx_data = yaml.safe_load(f)
|
|
568
|
+
jinxs.append(jinx_data)
|
|
569
|
+
except Exception as e:
|
|
570
|
+
print(f"Error loading project jinx {path}: {e}")
|
|
571
|
+
return jsonify({"jinxs": jinxs})
|
|
555
572
|
|
|
556
573
|
@app.route("/api/jinx/execute", methods=["POST"])
|
|
557
574
|
def execute_jinx():
|
|
@@ -568,8 +585,11 @@ def execute_jinx():
|
|
|
568
585
|
with cancellation_lock:
|
|
569
586
|
cancellation_flags[stream_id] = False
|
|
570
587
|
|
|
588
|
+
print(data)
|
|
589
|
+
|
|
571
590
|
jinx_name = data.get("jinxName")
|
|
572
591
|
jinx_args = data.get("jinxArgs", [])
|
|
592
|
+
print(jinx_args)
|
|
573
593
|
conversation_id = data.get("conversationId")
|
|
574
594
|
model = data.get("model")
|
|
575
595
|
provider = data.get("provider")
|
|
@@ -616,8 +636,45 @@ def execute_jinx():
|
|
|
616
636
|
|
|
617
637
|
# Extract inputs from args
|
|
618
638
|
from npcpy.npc_compiler import extract_jinx_inputs
|
|
619
|
-
|
|
620
|
-
|
|
639
|
+
|
|
640
|
+
# --- Start of Fix ---
|
|
641
|
+
# Re-assemble arguments that were incorrectly split by spaces.
|
|
642
|
+
fixed_args = []
|
|
643
|
+
i = 0
|
|
644
|
+
while i < len(jinx_args):
|
|
645
|
+
arg = jinx_args[i]
|
|
646
|
+
if arg.startswith('-'):
|
|
647
|
+
fixed_args.append(arg)
|
|
648
|
+
value_parts = []
|
|
649
|
+
i += 1
|
|
650
|
+
# Collect all subsequent parts until the next flag or the end of the list.
|
|
651
|
+
while i < len(jinx_args) and not jinx_args[i].startswith('-'):
|
|
652
|
+
value_parts.append(jinx_args[i])
|
|
653
|
+
i += 1
|
|
654
|
+
|
|
655
|
+
if value_parts:
|
|
656
|
+
# Join the parts back into a single string.
|
|
657
|
+
full_value = " ".join(value_parts)
|
|
658
|
+
# Clean up the extraneous quotes that the initial bad split left behind.
|
|
659
|
+
if full_value.startswith("'") and full_value.endswith("'"):
|
|
660
|
+
full_value = full_value[1:-1]
|
|
661
|
+
elif full_value.startswith('"') and full_value.endswith('"'):
|
|
662
|
+
full_value = full_value[1:-1]
|
|
663
|
+
fixed_args.append(full_value)
|
|
664
|
+
# The 'i' counter is already advanced, so the loop continues from the next flag.
|
|
665
|
+
else:
|
|
666
|
+
# This handles positional arguments, just in case.
|
|
667
|
+
fixed_args.append(arg)
|
|
668
|
+
i += 1
|
|
669
|
+
# --- End of Fix ---
|
|
670
|
+
|
|
671
|
+
# Now, use the corrected arguments to extract inputs.
|
|
672
|
+
input_values = extract_jinx_inputs(fixed_args, jinx)
|
|
673
|
+
|
|
674
|
+
|
|
675
|
+
|
|
676
|
+
|
|
677
|
+
print('executing jinx with input_values ,', input_values)
|
|
621
678
|
# Get conversation history
|
|
622
679
|
command_history = CommandHistory(app.config.get('DB_PATH'))
|
|
623
680
|
messages = fetch_messages_for_conversation(conversation_id)
|
|
@@ -966,49 +1023,6 @@ def get_npc_team_global():
|
|
|
966
1023
|
return jsonify({"npcs": [], "error": str(e)})
|
|
967
1024
|
|
|
968
1025
|
|
|
969
|
-
@app.route("/api/jinxs/global", methods=["GET"])
|
|
970
|
-
def get_global_jinxs():
|
|
971
|
-
|
|
972
|
-
user_home = os.path.expanduser("~")
|
|
973
|
-
jinxs_dir = os.path.join(user_home, ".npcsh", "npc_team", "jinxs")
|
|
974
|
-
jinxs = []
|
|
975
|
-
if os.path.exists(jinxs_dir):
|
|
976
|
-
for file in os.listdir(jinxs_dir):
|
|
977
|
-
if file.endswith(".jinx"):
|
|
978
|
-
with open(os.path.join(jinxs_dir, file), "r") as f:
|
|
979
|
-
jinx_data = yaml.safe_load(f)
|
|
980
|
-
jinxs.append(jinx_data)
|
|
981
|
-
print("file", file)
|
|
982
|
-
|
|
983
|
-
return jsonify({"jinxs": jinxs})
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
@app.route("/api/jinxs/project", methods=["GET"])
|
|
991
|
-
def get_project_jinxs():
|
|
992
|
-
current_path = request.args.get(
|
|
993
|
-
"currentPath"
|
|
994
|
-
)
|
|
995
|
-
if not current_path:
|
|
996
|
-
return jsonify({"jinxs": []})
|
|
997
|
-
|
|
998
|
-
if not current_path.endswith("npc_team"):
|
|
999
|
-
current_path = os.path.join(current_path, "npc_team")
|
|
1000
|
-
|
|
1001
|
-
jinxs_dir = os.path.join(current_path, "jinxs")
|
|
1002
|
-
jinxs = []
|
|
1003
|
-
if os.path.exists(jinxs_dir):
|
|
1004
|
-
for file in os.listdir(jinxs_dir):
|
|
1005
|
-
if file.endswith(".jinx"):
|
|
1006
|
-
with open(os.path.join(jinxs_dir, file), "r") as f:
|
|
1007
|
-
jinx_data = yaml.safe_load(f)
|
|
1008
|
-
jinxs.append(jinx_data)
|
|
1009
|
-
return jsonify({"jinxs": jinxs})
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
1026
|
@app.route("/api/jinxs/save", methods=["POST"])
|
|
1013
1027
|
def save_jinx():
|
|
1014
1028
|
try:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: npcpy
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.28
|
|
4
4
|
Summary: npcpy is the premier open-source library for integrating LLMs and Agents into python systems.
|
|
5
5
|
Home-page: https://github.com/NPC-Worldwide/npcpy
|
|
6
6
|
Author: Christopher Agostino
|
|
@@ -330,7 +330,7 @@ Users are not required to pass agents to get_llm_response, so you can work with
|
|
|
330
330
|
```python
|
|
331
331
|
from npcpy.npc_sysenv import print_and_process_stream
|
|
332
332
|
from npcpy.llm_funcs import get_llm_response
|
|
333
|
-
response = get_llm_response("When did the united states government begin sending advisors to vietnam?", model='
|
|
333
|
+
response = get_llm_response("When did the united states government begin sending advisors to vietnam?", model='qwen3:latest', provider='ollama', stream = True)
|
|
334
334
|
|
|
335
335
|
full_response = print_and_process_stream(response['response'], 'llama3.2', 'ollama')
|
|
336
336
|
```
|
|
@@ -338,7 +338,7 @@ Return structured outputs by specifying `format='json'` or passing a Pydantic sc
|
|
|
338
338
|
|
|
339
339
|
```python
|
|
340
340
|
from npcpy.llm_funcs import get_llm_response
|
|
341
|
-
response = get_llm_response("What is the sentiment of the american people towards the repeal of Roe v Wade? Return a json object with `sentiment` as the key and a float value from -1 to 1 as the value", model='
|
|
341
|
+
response = get_llm_response("What is the sentiment of the american people towards the repeal of Roe v Wade? Return a json object with `sentiment` as the key and a float value from -1 to 1 as the value", model='claude-4-5-haiku-latest', provider='deepseek', format='json')
|
|
342
342
|
|
|
343
343
|
print(response['response'])
|
|
344
344
|
```
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|