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.
Files changed (72) hide show
  1. {npcpy-1.2.27/npcpy.egg-info → npcpy-1.2.28}/PKG-INFO +3 -3
  2. {npcpy-1.2.27 → npcpy-1.2.28}/README.md +2 -2
  3. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/npc_compiler.py +23 -24
  4. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/serve.py +96 -82
  5. {npcpy-1.2.27 → npcpy-1.2.28/npcpy.egg-info}/PKG-INFO +3 -3
  6. {npcpy-1.2.27 → npcpy-1.2.28}/setup.py +1 -1
  7. {npcpy-1.2.27 → npcpy-1.2.28}/LICENSE +0 -0
  8. {npcpy-1.2.27 → npcpy-1.2.28}/MANIFEST.in +0 -0
  9. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/__init__.py +0 -0
  10. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/data/__init__.py +0 -0
  11. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/data/audio.py +0 -0
  12. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/data/data_models.py +0 -0
  13. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/data/image.py +0 -0
  14. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/data/load.py +0 -0
  15. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/data/text.py +0 -0
  16. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/data/video.py +0 -0
  17. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/data/web.py +0 -0
  18. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/ft/__init__.py +0 -0
  19. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/ft/diff.py +0 -0
  20. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/ft/ge.py +0 -0
  21. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/ft/memory_trainer.py +0 -0
  22. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/ft/model_ensembler.py +0 -0
  23. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/ft/rl.py +0 -0
  24. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/ft/sft.py +0 -0
  25. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/ft/usft.py +0 -0
  26. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/gen/__init__.py +0 -0
  27. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/gen/audio_gen.py +0 -0
  28. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/gen/embeddings.py +0 -0
  29. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/gen/image_gen.py +0 -0
  30. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/gen/response.py +0 -0
  31. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/gen/video_gen.py +0 -0
  32. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/llm_funcs.py +0 -0
  33. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/main.py +0 -0
  34. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/memory/__init__.py +0 -0
  35. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/memory/command_history.py +0 -0
  36. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/memory/kg_vis.py +0 -0
  37. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/memory/knowledge_graph.py +0 -0
  38. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/memory/memory_processor.py +0 -0
  39. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/memory/search.py +0 -0
  40. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/mix/__init__.py +0 -0
  41. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/mix/debate.py +0 -0
  42. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/npc_sysenv.py +0 -0
  43. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/npcs.py +0 -0
  44. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/sql/__init__.py +0 -0
  45. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/sql/ai_function_tools.py +0 -0
  46. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/sql/database_ai_adapters.py +0 -0
  47. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/sql/database_ai_functions.py +0 -0
  48. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/sql/model_runner.py +0 -0
  49. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/sql/npcsql.py +0 -0
  50. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/sql/sql_model_compiler.py +0 -0
  51. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/tools.py +0 -0
  52. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/work/__init__.py +0 -0
  53. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/work/desktop.py +0 -0
  54. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/work/plan.py +0 -0
  55. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy/work/trigger.py +0 -0
  56. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy.egg-info/SOURCES.txt +0 -0
  57. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy.egg-info/dependency_links.txt +0 -0
  58. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy.egg-info/requires.txt +0 -0
  59. {npcpy-1.2.27 → npcpy-1.2.28}/npcpy.egg-info/top_level.txt +0 -0
  60. {npcpy-1.2.27 → npcpy-1.2.28}/setup.cfg +0 -0
  61. {npcpy-1.2.27 → npcpy-1.2.28}/tests/test_audio.py +0 -0
  62. {npcpy-1.2.27 → npcpy-1.2.28}/tests/test_command_history.py +0 -0
  63. {npcpy-1.2.27 → npcpy-1.2.28}/tests/test_image.py +0 -0
  64. {npcpy-1.2.27 → npcpy-1.2.28}/tests/test_llm_funcs.py +0 -0
  65. {npcpy-1.2.27 → npcpy-1.2.28}/tests/test_load.py +0 -0
  66. {npcpy-1.2.27 → npcpy-1.2.28}/tests/test_npc_compiler.py +0 -0
  67. {npcpy-1.2.27 → npcpy-1.2.28}/tests/test_npcsql.py +0 -0
  68. {npcpy-1.2.27 → npcpy-1.2.28}/tests/test_response.py +0 -0
  69. {npcpy-1.2.27 → npcpy-1.2.28}/tests/test_serve.py +0 -0
  70. {npcpy-1.2.27 → npcpy-1.2.28}/tests/test_text.py +0 -0
  71. {npcpy-1.2.27 → npcpy-1.2.28}/tests/test_tools.py +0 -0
  72. {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.27
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='qwen2.5:14b', provider='ollama', stream = True)
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='deepseek-coder', provider='deepseek', format='json')
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='qwen2.5:14b', provider='ollama', stream = True)
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='deepseek-coder', provider='deepseek', format='json')
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 filename in os.listdir(directory):
490
- if filename.endswith(".jinx"):
491
- try:
492
- jinx_path = os.path.join(directory, 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}")
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
- npc_jinxs.extend(load_jinxs_from_directory(self.jinxs_directory))
1066
-
1067
- if os.path.exists(self.jinxs_directory):
1068
- npc_jinxs.extend(load_jinxs_from_directory(self.jinxs_directory))
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
- npc_name = request.args.get('npc')
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
- if os.path.exists(team_jinxs_dir):
523
- for file in os.listdir(team_jinxs_dir):
524
- if file.endswith('.jinx'):
525
- jinx_names.add(file[:-5]) # Remove .jinx extension
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
- if os.path.exists(global_jinxs_dir):
530
- for file in os.listdir(global_jinxs_dir):
531
- if file.endswith('.jinx'):
532
- jinx_names.add(file[:-5])
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
- input_values = extract_jinx_inputs(jinx_args, jinx)
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.27
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='qwen2.5:14b', provider='ollama', stream = True)
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='deepseek-coder', provider='deepseek', format='json')
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
  ```
@@ -83,7 +83,7 @@ extra_files = package_files("npcpy/npc_team/")
83
83
 
84
84
  setup(
85
85
  name="npcpy",
86
- version="1.2.27",
86
+ version="1.2.28",
87
87
  packages=find_packages(exclude=["tests*"]),
88
88
  install_requires=base_requirements,
89
89
  extras_require={
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