npcpy 1.3.4__py3-none-any.whl → 1.3.5__py3-none-any.whl

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/sql/npcsql.py CHANGED
@@ -7,6 +7,12 @@ from collections import defaultdict, deque
7
7
  from sqlalchemy import create_engine, text, Engine, inspect
8
8
  import inspect as py_inspect
9
9
 
10
+ try:
11
+ from jinja2 import Environment, BaseLoader, DebugUndefined
12
+ JINJA_AVAILABLE = True
13
+ except ImportError:
14
+ JINJA_AVAILABLE = False
15
+
10
16
  # --- Explicitly import llm_funcs as a module object ---
11
17
  try:
12
18
  import npcpy.llm_funcs as llm_funcs
@@ -74,10 +80,8 @@ class DatabaseAIFunctionMapper:
74
80
  'cortex_function': 'COMPLETE',
75
81
  'transformer': lambda prompt, **kwargs: f"SNOWFLAKE.CORTEX.COMPLETE('llama3.1-8b', {prompt})"
76
82
  },
77
- 'extract_facts': {
78
- 'cortex_function': 'COMPLETE',
79
- 'transformer': lambda text, **kwargs: f"SNOWFLAKE.CORTEX.COMPLETE('llama3.1-8b', CONCAT('Extract concise facts from this text. Return JSON with fact_list array. Text: ', {text}))"
80
- },
83
+
84
+
81
85
  'get_facts': {
82
86
  'cortex_function': 'COMPLETE',
83
87
  'transformer': lambda text, **kwargs: f"""SNOWFLAKE.CORTEX.COMPLETE('llama3.1-8b',
@@ -189,42 +193,183 @@ class NativeDatabaseAITransformer:
189
193
 
190
194
  return transformer(**kwargs)
191
195
 
196
+
197
+ # --- NQL Jinja Context ---
198
+ class NQLJinjaContext:
199
+ """Provides Jinja template context for NQL models with access to NPCs, jinxs, and team."""
200
+
201
+ def __init__(self, team=None, npc_operations=None):
202
+ self.team = team
203
+ self.npc_operations = npc_operations
204
+ self._npc_cache = {}
205
+ self._jinx_cache = {}
206
+
207
+ def npc(self, name: str) -> dict:
208
+ """Get NPC properties by name. Usage: {{ npc('sibiji').model }}"""
209
+ if name in self._npc_cache:
210
+ return self._npc_cache[name]
211
+
212
+ if not self.team:
213
+ return {'name': name, 'error': 'No team loaded'}
214
+
215
+ npc_obj = self.team.get_npc(name)
216
+ if not npc_obj:
217
+ return {'name': name, 'error': f'NPC {name} not found'}
218
+
219
+ # Build properties dict
220
+ props = {
221
+ 'name': getattr(npc_obj, 'name', name),
222
+ 'model': getattr(npc_obj, 'model', 'gpt-4o-mini'),
223
+ 'provider': getattr(npc_obj, 'provider', 'openai'),
224
+ 'directive': getattr(npc_obj, 'primary_directive', ''),
225
+ 'jinxs': getattr(npc_obj, 'jinxs', []),
226
+ }
227
+ self._npc_cache[name] = props
228
+ return props
229
+
230
+ def jinx(self, name: str) -> dict:
231
+ """Get jinx properties by name. Usage: {{ jinx('sample').description }}"""
232
+ if name in self._jinx_cache:
233
+ return self._jinx_cache[name]
234
+
235
+ if not self.npc_operations or not self.npc_operations.jinx_map:
236
+ return {'name': name, 'error': 'No jinxs loaded'}
237
+
238
+ jinx_info = self.npc_operations.jinx_map.get(name.lower())
239
+ if not jinx_info:
240
+ return {'name': name, 'error': f'Jinx {name} not found'}
241
+
242
+ props = {
243
+ 'name': jinx_info.get('name', name),
244
+ 'description': jinx_info.get('description', ''),
245
+ 'inputs': jinx_info.get('inputs', []),
246
+ }
247
+ self._jinx_cache[name] = props
248
+ return props
249
+
250
+ def get_team_context(self) -> dict:
251
+ """Get team-level properties. Usage: {{ team.forenpc }}"""
252
+ if not self.team:
253
+ return {'error': 'No team loaded'}
254
+
255
+ return {
256
+ 'name': getattr(self.team, 'name', 'npc_team'),
257
+ 'forenpc': getattr(self.team, 'forenpc_name', None),
258
+ 'npcs': [getattr(n, 'name', str(n)) for n in getattr(self.team, 'npcs', [])],
259
+ 'jinx_count': len(self.npc_operations.jinx_map) if self.npc_operations else 0,
260
+ }
261
+
262
+ def ref(self, model_name: str) -> str:
263
+ """Reference another model. Usage: {{ ref('base_stats') }}"""
264
+ return f"{{{{ ref('{model_name}') }}}}"
265
+
266
+ def config(self, **kwargs) -> str:
267
+ """Model configuration. Usage: {{ config(materialized='table') }}"""
268
+ config_parts = [f"{k}='{v}'" if isinstance(v, str) else f"{k}={v}"
269
+ for k, v in kwargs.items()]
270
+ return f"{{{{ config({', '.join(config_parts)}) }}}}"
271
+
272
+ def env(self, var_name: str, default: str = '') -> str:
273
+ """Get environment variable. Usage: {{ env('API_KEY') }}"""
274
+ return os.environ.get(var_name, default)
275
+
276
+ def build_jinja_env(self) -> 'Environment':
277
+ """Build Jinja2 environment with NQL functions."""
278
+ if not JINJA_AVAILABLE:
279
+ raise ImportError("Jinja2 is required for template processing. Install with: pip install jinja2")
280
+
281
+ env = Environment(
282
+ loader=BaseLoader(),
283
+ undefined=DebugUndefined,
284
+ # Keep {{ ref(...) }} and {{ config(...) }} unprocessed for later
285
+ variable_start_string='{%',
286
+ variable_end_string='%}',
287
+ block_start_string='{%%',
288
+ block_end_string='%%}',
289
+ )
290
+
291
+ # Add custom functions
292
+ env.globals['npc'] = self.npc
293
+ env.globals['jinx'] = self.jinx
294
+ env.globals['team'] = self.get_team_context()
295
+ env.globals['env'] = self.env
296
+
297
+ return env
298
+
299
+ def render_template(self, content: str) -> str:
300
+ """Render Jinja template in SQL content."""
301
+ if not JINJA_AVAILABLE:
302
+ return content
303
+
304
+ # Only process if there are NQL Jinja expressions ({% ... %})
305
+ if '{%' not in content:
306
+ return content
307
+
308
+ try:
309
+ env = self.build_jinja_env()
310
+ template = env.from_string(content)
311
+ return template.render()
312
+ except Exception as e:
313
+ print(f"Warning: Jinja template error: {e}")
314
+ return content
315
+
316
+
192
317
  # --- NPCSQL Operations ---
193
318
  class NPCSQLOperations:
194
319
  def __init__(
195
- self,
196
- npc_directory: str,
320
+ self,
321
+ npc_directory: str,
197
322
  db_engine: Union[str, Engine] = "~/npcsh_history.db"
198
323
  ):
199
324
  self.npc_directory = npc_directory
200
-
325
+
201
326
  if isinstance(db_engine, str):
202
327
  self.engine = create_engine_from_path(db_engine)
203
328
  else:
204
329
  self.engine = db_engine
205
-
330
+
206
331
  self.npc_loader = None
332
+ self.jinx_map = {} # Maps jinx names to jinx objects
207
333
  self.function_map = self._build_function_map()
208
-
334
+
209
335
  def _get_team(self):
210
- return (self.npc_loader
211
- if hasattr(self.npc_loader, 'npcs')
336
+ return (self.npc_loader
337
+ if hasattr(self.npc_loader, 'npcs')
212
338
  else None)
213
339
 
214
340
  def _build_function_map(self):
215
341
  import types
216
-
342
+
217
343
  function_map = {}
218
344
  for name in dir(llm_funcs):
219
345
  if name.startswith('_'):
220
346
  continue
221
347
  obj = getattr(llm_funcs, name)
222
- if (isinstance(obj, types.FunctionType) or
348
+ if (isinstance(obj, types.FunctionType) or
223
349
  (isinstance(obj, types.MethodType) and obj.__self__ is not None)):
224
350
  function_map[name] = obj
225
-
351
+
226
352
  return function_map
227
353
 
354
+ def load_team_jinxs(self, team):
355
+ """Load jinxs from team to make them available as NQL functions."""
356
+ if not team:
357
+ return
358
+
359
+ try:
360
+ # Get all jinxs from the team's jinx catalog
361
+ if hasattr(team, 'jinx_tool_catalog'):
362
+ for tool in team.jinx_tool_catalog:
363
+ jinx_name = tool.get('name', '').lower()
364
+ if jinx_name and jinx_name not in self.function_map:
365
+ # Store reference to the jinx
366
+ self.jinx_map[jinx_name] = tool
367
+ # Add a placeholder to function_map so it's recognized
368
+ self.function_map[jinx_name] = f"__jinx__{jinx_name}"
369
+ print(f"NQL: Registered team jinx '{jinx_name}' as NQL function")
370
+ except Exception as e:
371
+ print(f"Warning: Could not load team jinxs: {e}")
372
+
228
373
  def _resolve_npc_reference(self, npc_ref: str):
229
374
  if not npc_ref or not self.npc_loader:
230
375
  return None
@@ -252,6 +397,37 @@ class NPCSQLOperations:
252
397
 
253
398
  return None
254
399
 
400
+ def _execute_jinx(self, jinx_name: str, query: str, npc_ref: str, context: str = "") -> str:
401
+ """Execute a team jinx and return the result."""
402
+ try:
403
+ from npcpy.npc_compiler import execute_jinx
404
+
405
+ jinx_info = self.jinx_map.get(jinx_name)
406
+ if not jinx_info:
407
+ return f"Error: Jinx '{jinx_name}' not found"
408
+
409
+ # Build context for jinx execution
410
+ jinx_context = {
411
+ 'input': query,
412
+ 'prompt': query,
413
+ 'text': query,
414
+ 'context': context,
415
+ }
416
+
417
+ # Get the jinx object from team
418
+ team = self._get_team()
419
+ if team and hasattr(team, 'get_jinx'):
420
+ jinx = team.get_jinx(jinx_name)
421
+ if jinx:
422
+ result = execute_jinx(jinx, jinx_context, team=team)
423
+ if isinstance(result, dict):
424
+ return result.get('output', str(result))
425
+ return str(result)
426
+
427
+ return f"Error: Could not execute jinx '{jinx_name}'"
428
+ except Exception as e:
429
+ return f"Jinx error: {e}"
430
+
255
431
  def execute_ai_function(
256
432
  self,
257
433
  func_name: str,
@@ -262,6 +438,7 @@ class NPCSQLOperations:
262
438
  raise ValueError(f"Unknown AI function: {func_name}")
263
439
 
264
440
  func = self.function_map[func_name]
441
+ is_jinx = isinstance(func, str) and func.startswith("__jinx__")
265
442
 
266
443
  npc_ref = params.get('npc', '')
267
444
  resolved_npc = self._resolve_npc_reference(npc_ref)
@@ -271,7 +448,8 @@ class NPCSQLOperations:
271
448
  resolved_team = resolved_npc.team
272
449
 
273
450
  total_rows = len(df)
274
- print(f"NQL: Executing {func_name} on {total_rows} rows with NPC '{npc_ref}'...")
451
+ func_type = "jinx" if is_jinx else "function"
452
+ print(f"NQL: Executing {func_type} '{func_name}' on {total_rows} rows with NPC '{npc_ref}'...")
275
453
 
276
454
  results = []
277
455
  for idx, (row_idx, row) in enumerate(df.iterrows()):
@@ -292,34 +470,45 @@ class NPCSQLOperations:
292
470
 
293
471
  print(f" [{idx+1}/{total_rows}] Processing row {row_idx}...", end=" ", flush=True)
294
472
 
295
- sig = py_inspect.signature(func)
296
-
297
- # Extract model/provider from NPC if available
298
- npc_model = None
299
- npc_provider = None
300
- if resolved_npc and hasattr(resolved_npc, 'model'):
301
- npc_model = resolved_npc.model
302
- if resolved_npc and hasattr(resolved_npc, 'provider'):
303
- npc_provider = resolved_npc.provider
304
-
305
- func_params = {
306
- k: v for k, v in {
307
- 'prompt': query,
308
- 'text': query,
309
- 'npc': resolved_npc,
310
- 'team': resolved_team,
311
- 'context': params.get('context', ''),
312
- 'model': npc_model or 'gpt-4o-mini',
313
- 'provider': npc_provider or 'openai'
314
- }.items() if k in sig.parameters
315
- }
316
-
317
473
  try:
318
- result = func(**func_params)
319
- result_value = (result.get("response", "")
320
- if isinstance(result, dict)
321
- else str(result))
322
- print(f"OK ({len(result_value)} chars)")
474
+ if is_jinx:
475
+ # Execute as jinx
476
+ result_value = self._execute_jinx(
477
+ func_name,
478
+ query,
479
+ npc_ref,
480
+ params.get('context', '')
481
+ )
482
+ else:
483
+ # Execute as llm_func
484
+ sig = py_inspect.signature(func)
485
+
486
+ # Extract model/provider from NPC if available
487
+ npc_model = None
488
+ npc_provider = None
489
+ if resolved_npc and hasattr(resolved_npc, 'model'):
490
+ npc_model = resolved_npc.model
491
+ if resolved_npc and hasattr(resolved_npc, 'provider'):
492
+ npc_provider = resolved_npc.provider
493
+
494
+ func_params = {
495
+ k: v for k, v in {
496
+ 'prompt': query,
497
+ 'text': query,
498
+ 'npc': resolved_npc,
499
+ 'team': resolved_team,
500
+ 'context': params.get('context', ''),
501
+ 'model': npc_model or 'gpt-4o-mini',
502
+ 'provider': npc_provider or 'openai'
503
+ }.items() if k in sig.parameters
504
+ }
505
+
506
+ result = func(**func_params)
507
+ result_value = (result.get("response", "")
508
+ if isinstance(result, dict)
509
+ else str(result))
510
+
511
+ print(f"OK ({len(str(result_value))} chars)")
323
512
  except Exception as e:
324
513
  print(f"ERROR: {e}")
325
514
  result_value = None
@@ -333,20 +522,22 @@ class NPCSQLOperations:
333
522
  # --- SQL Model Definition ---
334
523
  class SQLModel:
335
524
  def __init__(
336
- self,
337
- name: str,
338
- content: str,
339
- path: str,
340
- npc_directory: str
525
+ self,
526
+ name: str,
527
+ content: str,
528
+ path: str,
529
+ npc_directory: str,
530
+ additional_functions: Optional[List[str]] = None
341
531
  ):
342
532
  self.name = name
343
533
  self.content = content
344
534
  self.path = path
345
535
  self.npc_directory = npc_directory
346
-
536
+ self.additional_functions = additional_functions or []
537
+
347
538
  config_match = re.search(
348
- r'\{\{[\s]*config\((.*?)\)[\s]*\}\}',
349
- content,
539
+ r'\{\{[\s]*config\((.*?)\)[\s]*\}\}',
540
+ content,
350
541
  re.DOTALL
351
542
  )
352
543
  if config_match:
@@ -356,7 +547,7 @@ class SQLModel:
356
547
 
357
548
  self.dependencies = self._extract_dependencies()
358
549
  self.has_ai_function = self._check_ai_functions()
359
-
550
+
360
551
  # DEBUG print to confirm if AI functions are found
361
552
  self.ai_functions = self._extract_ai_functions()
362
553
  if self.ai_functions:
@@ -397,9 +588,15 @@ class SQLModel:
397
588
  if name.startswith('_'):
398
589
  continue
399
590
  obj = getattr(llm_funcs, name)
400
- if (isinstance(obj, types.FunctionType) or
591
+ if (isinstance(obj, types.FunctionType) or
401
592
  (isinstance(obj, types.MethodType) and obj.__self__ is not None)):
402
593
  available_functions.append(name.lower()) # Store as lowercase for comparison
594
+
595
+ # Add any additional functions (e.g., team jinxs)
596
+ for fn in self.additional_functions:
597
+ fn_lower = fn.lower()
598
+ if fn_lower not in available_functions:
599
+ available_functions.append(fn_lower)
403
600
 
404
601
  for match in matches:
405
602
  full_call_string = match.group(0).strip()
@@ -496,9 +693,17 @@ class ModelCompiler:
496
693
  try:
497
694
  self.npc_team = Team(team_path=npc_directory)
498
695
  self.npc_operations.npc_loader = self.npc_team
696
+ # Load team jinxs as NQL functions
697
+ self.npc_operations.load_team_jinxs(self.npc_team)
499
698
  except Exception as e:
500
699
  self.npc_team = None
501
700
  print(f"Warning: Could not load NPC team from {npc_directory}. AI functions relying on NPC context might fail: {e}")
701
+
702
+ # Initialize Jinja context for template processing
703
+ self.jinja_context = NQLJinjaContext(
704
+ team=self.npc_team,
705
+ npc_operations=self.npc_operations
706
+ )
502
707
 
503
708
  def _get_engine(self, source_name: str) -> Engine:
504
709
  if source_name.lower() == 'local' or not self.external_engines:
@@ -516,19 +721,27 @@ class ModelCompiler:
516
721
  def discover_models(self):
517
722
  self.models = {}
518
723
  sql_files = list(self.models_dir.glob("**/*.sql"))
519
-
724
+
725
+ # Get list of available jinx names for NQL function recognition
726
+ additional_funcs = list(self.npc_operations.jinx_map.keys())
727
+
520
728
  for sql_file in sql_files:
521
729
  model_name = sql_file.stem
522
730
  with open(sql_file, "r") as f:
523
731
  content = f.read()
524
-
732
+
733
+ # Process Jinja templates ({% npc(...) %}, {% team.forenpc %}, etc.)
734
+ if JINJA_AVAILABLE and '{%' in content:
735
+ content = self.jinja_context.render_template(content)
736
+
525
737
  self.models[model_name] = SQLModel(
526
- model_name,
527
- content,
528
- str(sql_file),
529
- str(sql_file.parent)
738
+ model_name,
739
+ content,
740
+ str(sql_file),
741
+ str(sql_file.parent),
742
+ additional_functions=additional_funcs
530
743
  )
531
-
744
+
532
745
  return self.models
533
746
 
534
747
  def build_dag(self) -> Dict[str, Set[str]]:
npcpy/work/browser.py ADDED
@@ -0,0 +1,30 @@
1
+ """
2
+ Global browser session storage for selenium automation.
3
+ """
4
+
5
+ _sessions = {}
6
+
7
+ def get_sessions():
8
+ return _sessions
9
+
10
+ def get_current_driver():
11
+ current = _sessions.get('current')
12
+ if current and current in _sessions:
13
+ return _sessions[current]
14
+ return None
15
+
16
+ def set_driver(session_id, driver):
17
+ _sessions[session_id] = driver
18
+ _sessions['current'] = session_id
19
+
20
+ def close_current():
21
+ current = _sessions.get('current')
22
+ if current and current in _sessions:
23
+ try:
24
+ _sessions[current].quit()
25
+ except:
26
+ pass
27
+ del _sessions[current]
28
+ _sessions['current'] = None
29
+ return True
30
+ return False
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: npcpy
3
- Version: 1.3.4
3
+ Version: 1.3.5
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
@@ -1,21 +1,22 @@
1
1
  npcpy/__init__.py,sha256=uJcJGjR1mWvE69GySNAufkgiRwJA28zdObDBWaxp0tY,505
2
- npcpy/llm_funcs.py,sha256=sc-sXA48VpJFy7vWyh8M5ZY2HQ362le_BfAtDA3Gh7Y,76489
2
+ npcpy/build_funcs.py,sha256=vOz6pjV0zS-kYKo0ux-pn9AcppVaR8KIDi2ldOxb3RQ,7479
3
+ npcpy/llm_funcs.py,sha256=E0HCVD98YFG8yMm5Pvlo8AatvxRykaE4DyX5LqrJTM8,75046
3
4
  npcpy/main.py,sha256=RWoRIj6VQLxKdOKvdVyaq2kwG35oRpeXPvp1CAAoG-w,81
4
5
  npcpy/ml_funcs.py,sha256=UI7k7JR4XOH_VXR-xxLaO4r9Kyx_jBaEnp3TUIY7ZLQ,22657
5
6
  npcpy/npc_array.py,sha256=fVTxcMiXV-lvltmuwaRnTU9D3ikPq3-7k5wzp7MA5OY,40224
6
- npcpy/npc_compiler.py,sha256=X2BjMqKL7hbS37PPkSDGgZSF_PF_GNVGLd92ePRNRwQ,111868
7
- npcpy/npc_sysenv.py,sha256=rtE3KrXvIuOEpMq1CW5eK5K0o3f6mXagNXCeMnhHob4,36736
7
+ npcpy/npc_compiler.py,sha256=trMvZHZjGDHo0TvjxZc8QJZXit78-rPDpxU0wsxtocw,118139
8
+ npcpy/npc_sysenv.py,sha256=E4_C0UxuIasQ0Ie--CVty3d6OfV9rHP86OhEelVZhLs,36780
8
9
  npcpy/npcs.py,sha256=eExuVsbTfrRobTRRptRpDm46jCLWUgbvy4_U7IUQo-c,744
9
- npcpy/serve.py,sha256=5S3v4lp3fPozsnp_48SuVenf3JTiSiIBRxgfAReovmM,181539
10
+ npcpy/serve.py,sha256=-Aia3kmjozo1aSQzIcEWZP7IcRSHyp5S4qTboX0iYgM,192944
10
11
  npcpy/tools.py,sha256=A5_oVmZkzGnI3BI-NmneuxeXQq-r29PbpAZP4nV4jrc,5303
11
12
  npcpy/data/__init__.py,sha256=1tcoChR-Hjn905JDLqaW9ElRmcISCTJdE7BGXPlym2Q,642
12
13
  npcpy/data/audio.py,sha256=3qryGXnWHa4JFMonjuX-lf0fCrF8jmbHe7mHAuOdua0,12397
13
14
  npcpy/data/data_models.py,sha256=q7xpI4_nK5HvlOE1XB5u5nFQs4SE5zcgt0kIZJF2dhs,682
14
15
  npcpy/data/image.py,sha256=UQcioNPDd5HYMLL_KStf45SuiIPXDcUY-dEFHwSWUeE,6564
15
- npcpy/data/load.py,sha256=7V-YBp_SaMzCfLfvvyRrRkZ4rZWeYFgM0-3qiEYOfcc,9227
16
+ npcpy/data/load.py,sha256=rVe1xSHerIpo6MDaY5eIeqRSm0gssX5sHukNsUNVwJw,9228
16
17
  npcpy/data/text.py,sha256=jP0a1qZZaSJdK-LdZTn2Jjdxqmkd3efxDLEoxflJQeY,5010
17
18
  npcpy/data/video.py,sha256=H-V3mTu_ktD9u-QhYeo4aW3u9z0AtoAdRZmvRPEpE98,2887
18
- npcpy/data/web.py,sha256=ARGoVKUlQmaiX0zJbSvvFmRCwOv_Z7Pcan9c5GxYObQ,5117
19
+ npcpy/data/web.py,sha256=pcjCLVAoqfw9enV5a7Dg1A_V7USG0302e6C7wUz2UgE,5235
19
20
  npcpy/ft/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
21
  npcpy/ft/diff.py,sha256=2-NbY0p0CP5Qr9mnnncxRBwzmxRq9NKcl8B5BeT1vQ4,12319
21
22
  npcpy/ft/ge.py,sha256=0VzIiXq2wCzGcK1x0Wd-myJ3xRf-FNaPg0GkHEZegUM,3552
@@ -27,14 +28,15 @@ npcpy/ft/usft.py,sha256=O025GGYGZQf2ZVLowyAmBwh5bJyuy2dUAM6v03YcboY,3435
27
28
  npcpy/gen/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
29
  npcpy/gen/audio_gen.py,sha256=w4toESu7nmli1T5FOwRRCGC_QK9W-SMWknYYkbRv9jE,635
29
30
  npcpy/gen/embeddings.py,sha256=QStTJ2ELiC379OEZsLEgGGIIFD267Y8zQchs7HRn2Zg,2089
30
- npcpy/gen/image_gen.py,sha256=VflU_wJsKWJarOVwZtL2M8ymDFfKNz8WX66Rwk4obeo,21778
31
+ npcpy/gen/image_gen.py,sha256=SOZYpvlxSiAdDK9j750OEBKjm22OUNdXg1kQ10sJSy0,21853
31
32
  npcpy/gen/ocr.py,sha256=rgmXWHrCYX1Po-qG_LrNFbVYEZ8aaupxFTgparcoB_Y,6554
32
- npcpy/gen/response.py,sha256=lH3fR3Sx1Cm8Zc0MJyHzTuuwTjVPgSJUZVxnkFIhzLE,40643
33
+ npcpy/gen/response.py,sha256=2QRyc8UJQmanUkDlwT09KjmveguNC411eSmdlUhLP04,43372
33
34
  npcpy/gen/video_gen.py,sha256=RFi3Zcq_Hn3HIcfoF3mijQ6G7RYFZaM_9pjPTh-8E64,3239
35
+ npcpy/gen/world_gen.py,sha256=_8ytE7E3QVQ5qiX8DmOby-xd0d9zV20rRI6Wkpf-qcY,18922
34
36
  npcpy/memory/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
- npcpy/memory/command_history.py,sha256=1488weOYtnm-wyenUvZKHaNgZe5OKOZSaQ35WNeceiM,56226
37
+ npcpy/memory/command_history.py,sha256=EEaBscup0YGA99ZHV8AzYBGUwRiI0nBTOPmLWvCbY-A,60362
36
38
  npcpy/memory/kg_vis.py,sha256=TrQQCRh_E7Pyr-GPAHLSsayubAfGyf4HOEFrPB6W86Q,31280
37
- npcpy/memory/knowledge_graph.py,sha256=2XpIlsyPdAOnzQ6kkwP6MWPGwL3P6V33_3suNJYMMJE,48681
39
+ npcpy/memory/knowledge_graph.py,sha256=FsMptito-wUcYOpRWEUxyTcmXPr-lxgHlMSy9xN7jAA,48677
38
40
  npcpy/memory/memory_processor.py,sha256=6PfVnSBA9ag5EhHJinXoODfEPTlDDoaT0PtCCuZO6HI,2598
39
41
  npcpy/memory/search.py,sha256=glN6WYzaixcoDphTEHAXSMX3vKZGjR12Jx9YVL_gYfE,18433
40
42
  npcpy/mix/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -44,14 +46,15 @@ npcpy/sql/ai_function_tools.py,sha256=ZCpjVHtaMRdL2dXxbQy5NhhjtPrVViGT1wyEl8ADrk
44
46
  npcpy/sql/database_ai_adapters.py,sha256=CMlNGOhmJZhGB47RPvLIMqB61m_eYPVg1lwx42_b0jQ,6865
45
47
  npcpy/sql/database_ai_functions.py,sha256=XQCmaFOE1lNCnwrLTNpotYOlv6sx41bb8hxZI_sqpy8,6335
46
48
  npcpy/sql/model_runner.py,sha256=hJZ7hx2mwI-8DAh47Q6BwOsRjx30-HzebL4ajEUO4HA,5734
47
- npcpy/sql/npcsql.py,sha256=YRBbcsMPNWLhzZqoF0wAL2MaT6OOc0wh33Z0hb01rjc,36591
49
+ npcpy/sql/npcsql.py,sha256=5pA2csm1igRSAPGoFYeTHo3dQRIVTvvMH1QMyMhPrcI,44663
48
50
  npcpy/sql/sql_model_compiler.py,sha256=G-0dpTlgzc-dXy9YEsdWGjO8xaQ3jFNbc6oUja1Ef4M,5364
49
51
  npcpy/work/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
+ npcpy/work/browser.py,sha256=p2PeaoZdAXipFuAgKCCB3aXXLE_p3yIRqC87KlZKZWc,679
50
53
  npcpy/work/desktop.py,sha256=F3I8mUtJp6LAkXodsh8hGZIncoads6c_2Utty-0EdDA,2986
51
54
  npcpy/work/plan.py,sha256=QyUwg8vElWiHuoS-xK4jXTxxHvkMD3VkaCEsCmrEPQk,8300
52
55
  npcpy/work/trigger.py,sha256=P1Y8u1wQRsS2WACims_2IdkBEar-iBQix-2TDWoW0OM,9948
53
- npcpy-1.3.4.dist-info/licenses/LICENSE,sha256=j0YPvce7Ng9e32zYOu0EmXjXeJ0Nwawd0RA3uSGGH4E,1070
54
- npcpy-1.3.4.dist-info/METADATA,sha256=-dPHdZlVOsr_QtmxxbLl7W4cSkXH8Ccaf-w-qRB0yAY,37884
55
- npcpy-1.3.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
56
- npcpy-1.3.4.dist-info/top_level.txt,sha256=g1pbSvrOOncB74Bg5-J0Olg4V0A5VzDw-Xz5YObq8BU,6
57
- npcpy-1.3.4.dist-info/RECORD,,
56
+ npcpy-1.3.5.dist-info/licenses/LICENSE,sha256=j0YPvce7Ng9e32zYOu0EmXjXeJ0Nwawd0RA3uSGGH4E,1070
57
+ npcpy-1.3.5.dist-info/METADATA,sha256=AvVXykxEQwTkZozgWXKY2YgAUHuoWqZQQxREx_hqyGg,37884
58
+ npcpy-1.3.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
59
+ npcpy-1.3.5.dist-info/top_level.txt,sha256=g1pbSvrOOncB74Bg5-J0Olg4V0A5VzDw-Xz5YObq8BU,6
60
+ npcpy-1.3.5.dist-info/RECORD,,
File without changes