npcsh 0.3.32__py3-none-any.whl → 1.0.0__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.
Files changed (93) hide show
  1. npcsh/_state.py +942 -0
  2. npcsh/alicanto.py +1074 -0
  3. npcsh/guac.py +785 -0
  4. npcsh/mcp_helpers.py +357 -0
  5. npcsh/mcp_npcsh.py +822 -0
  6. npcsh/mcp_server.py +184 -0
  7. npcsh/npc.py +218 -0
  8. npcsh/npcsh.py +1161 -0
  9. npcsh/plonk.py +387 -269
  10. npcsh/pti.py +234 -0
  11. npcsh/routes.py +958 -0
  12. npcsh/spool.py +315 -0
  13. npcsh/wander.py +550 -0
  14. npcsh/yap.py +573 -0
  15. npcsh-1.0.0.dist-info/METADATA +596 -0
  16. npcsh-1.0.0.dist-info/RECORD +21 -0
  17. {npcsh-0.3.32.dist-info → npcsh-1.0.0.dist-info}/WHEEL +1 -1
  18. npcsh-1.0.0.dist-info/entry_points.txt +9 -0
  19. {npcsh-0.3.32.dist-info → npcsh-1.0.0.dist-info}/licenses/LICENSE +1 -1
  20. npcsh/audio.py +0 -569
  21. npcsh/audio_gen.py +0 -1
  22. npcsh/cli.py +0 -543
  23. npcsh/command_history.py +0 -566
  24. npcsh/conversation.py +0 -54
  25. npcsh/data_models.py +0 -46
  26. npcsh/dataframes.py +0 -171
  27. npcsh/embeddings.py +0 -168
  28. npcsh/helpers.py +0 -646
  29. npcsh/image.py +0 -298
  30. npcsh/image_gen.py +0 -79
  31. npcsh/knowledge_graph.py +0 -1006
  32. npcsh/llm_funcs.py +0 -2195
  33. npcsh/load_data.py +0 -83
  34. npcsh/main.py +0 -5
  35. npcsh/model_runner.py +0 -189
  36. npcsh/npc_compiler.py +0 -2879
  37. npcsh/npc_sysenv.py +0 -388
  38. npcsh/npc_team/assembly_lines/test_pipeline.py +0 -181
  39. npcsh/npc_team/corca.npc +0 -13
  40. npcsh/npc_team/foreman.npc +0 -7
  41. npcsh/npc_team/npcsh.ctx +0 -11
  42. npcsh/npc_team/sibiji.npc +0 -4
  43. npcsh/npc_team/templates/analytics/celona.npc +0 -0
  44. npcsh/npc_team/templates/hr_support/raone.npc +0 -0
  45. npcsh/npc_team/templates/humanities/eriane.npc +0 -4
  46. npcsh/npc_team/templates/it_support/lineru.npc +0 -0
  47. npcsh/npc_team/templates/marketing/slean.npc +0 -4
  48. npcsh/npc_team/templates/philosophy/maurawa.npc +0 -0
  49. npcsh/npc_team/templates/sales/turnic.npc +0 -4
  50. npcsh/npc_team/templates/software/welxor.npc +0 -0
  51. npcsh/npc_team/tools/bash_executer.tool +0 -32
  52. npcsh/npc_team/tools/calculator.tool +0 -8
  53. npcsh/npc_team/tools/code_executor.tool +0 -16
  54. npcsh/npc_team/tools/generic_search.tool +0 -27
  55. npcsh/npc_team/tools/image_generation.tool +0 -25
  56. npcsh/npc_team/tools/local_search.tool +0 -149
  57. npcsh/npc_team/tools/npcsh_executor.tool +0 -9
  58. npcsh/npc_team/tools/screen_cap.tool +0 -27
  59. npcsh/npc_team/tools/sql_executor.tool +0 -26
  60. npcsh/response.py +0 -272
  61. npcsh/search.py +0 -252
  62. npcsh/serve.py +0 -1467
  63. npcsh/shell.py +0 -524
  64. npcsh/shell_helpers.py +0 -3919
  65. npcsh/stream.py +0 -233
  66. npcsh/video.py +0 -52
  67. npcsh/video_gen.py +0 -69
  68. npcsh-0.3.32.data/data/npcsh/npc_team/bash_executer.tool +0 -32
  69. npcsh-0.3.32.data/data/npcsh/npc_team/calculator.tool +0 -8
  70. npcsh-0.3.32.data/data/npcsh/npc_team/celona.npc +0 -0
  71. npcsh-0.3.32.data/data/npcsh/npc_team/code_executor.tool +0 -16
  72. npcsh-0.3.32.data/data/npcsh/npc_team/corca.npc +0 -13
  73. npcsh-0.3.32.data/data/npcsh/npc_team/eriane.npc +0 -4
  74. npcsh-0.3.32.data/data/npcsh/npc_team/foreman.npc +0 -7
  75. npcsh-0.3.32.data/data/npcsh/npc_team/generic_search.tool +0 -27
  76. npcsh-0.3.32.data/data/npcsh/npc_team/image_generation.tool +0 -25
  77. npcsh-0.3.32.data/data/npcsh/npc_team/lineru.npc +0 -0
  78. npcsh-0.3.32.data/data/npcsh/npc_team/local_search.tool +0 -149
  79. npcsh-0.3.32.data/data/npcsh/npc_team/maurawa.npc +0 -0
  80. npcsh-0.3.32.data/data/npcsh/npc_team/npcsh.ctx +0 -11
  81. npcsh-0.3.32.data/data/npcsh/npc_team/npcsh_executor.tool +0 -9
  82. npcsh-0.3.32.data/data/npcsh/npc_team/raone.npc +0 -0
  83. npcsh-0.3.32.data/data/npcsh/npc_team/screen_cap.tool +0 -27
  84. npcsh-0.3.32.data/data/npcsh/npc_team/sibiji.npc +0 -4
  85. npcsh-0.3.32.data/data/npcsh/npc_team/slean.npc +0 -4
  86. npcsh-0.3.32.data/data/npcsh/npc_team/sql_executor.tool +0 -26
  87. npcsh-0.3.32.data/data/npcsh/npc_team/test_pipeline.py +0 -181
  88. npcsh-0.3.32.data/data/npcsh/npc_team/turnic.npc +0 -4
  89. npcsh-0.3.32.data/data/npcsh/npc_team/welxor.npc +0 -0
  90. npcsh-0.3.32.dist-info/METADATA +0 -779
  91. npcsh-0.3.32.dist-info/RECORD +0 -78
  92. npcsh-0.3.32.dist-info/entry_points.txt +0 -3
  93. {npcsh-0.3.32.dist-info → npcsh-1.0.0.dist-info}/top_level.txt +0 -0
npcsh/helpers.py DELETED
@@ -1,646 +0,0 @@
1
- import logging
2
- from typing import List, Dict, Any, Optional
3
- import os
4
- import sqlite3
5
- import subprocess
6
- import platform
7
- import yaml
8
-
9
- try:
10
- import nltk
11
- except:
12
- print("Error importing nltk")
13
- import numpy as np
14
-
15
- import filecmp
16
-
17
- import shutil
18
- import tempfile
19
- import pandas as pd
20
-
21
- try:
22
- from sentence_transformers import util
23
- except Exception as e:
24
- print(f"Error importing sentence_transformers: {e}")
25
-
26
-
27
- def get_shell_config_file() -> str:
28
- """
29
-
30
- Function Description:
31
- This function returns the path to the shell configuration file.
32
- Args:
33
- None
34
- Keyword Args:
35
- None
36
- Returns:
37
- The path to the shell configuration file.
38
- """
39
- # Check the current shell
40
- shell = os.environ.get("SHELL", "")
41
-
42
- if "zsh" in shell:
43
- return os.path.expanduser("~/.zshrc")
44
- elif "bash" in shell:
45
- # On macOS, use .bash_profile for login shells
46
- if platform.system() == "Darwin":
47
- return os.path.expanduser("~/.bash_profile")
48
- else:
49
- return os.path.expanduser("~/.bashrc")
50
- else:
51
- # Default to .bashrc if we can't determine the shell
52
- return os.path.expanduser("~/.bashrc")
53
-
54
-
55
- def initial_table_print(cursor: sqlite3.Cursor) -> None:
56
- """
57
- Function Description:
58
- This function is used to print the initial table.
59
- Args:
60
- cursor : sqlite3.Cursor : The SQLite cursor.
61
- Keyword Args:
62
- None
63
- Returns:
64
- None
65
- """
66
-
67
- cursor.execute(
68
- "SELECT name FROM sqlite_master WHERE type='table' AND name != 'command_history'"
69
- )
70
- tables = cursor.fetchall()
71
-
72
- print("\nAvailable tables:")
73
- for i, table in enumerate(tables, 1):
74
- print(f"{i}. {table[0]}")
75
-
76
-
77
- def ensure_npcshrc_exists() -> str:
78
- """
79
- Function Description:
80
- This function ensures that the .npcshrc file exists in the user's home directory.
81
- Args:
82
- None
83
- Keyword Args:
84
- None
85
- Returns:
86
- The path to the .npcshrc file.
87
- """
88
-
89
- npcshrc_path = os.path.expanduser("~/.npcshrc")
90
- if not os.path.exists(npcshrc_path):
91
- with open(npcshrc_path, "w") as npcshrc:
92
- npcshrc.write("# NPCSH Configuration File\n")
93
- npcshrc.write("export NPCSH_INITIALIZED=0\n")
94
- npcshrc.write("export NPCSH_DEFAULT_MODE='chat'\n")
95
- npcshrc.write("export NPCSH_CHAT_PROVIDER='ollama'\n")
96
- npcshrc.write("export NPCSH_CHAT_MODEL='llama3.2'\n")
97
- npcshrc.write("export NPCSH_REASONING_PROVIDER='ollama'\n")
98
- npcshrc.write("export NPCSH_REASONING_MODEL='deepseek-r1'\n")
99
-
100
- npcshrc.write("export NPCSH_EMBEDDING_PROVIDER='ollama'\n")
101
- npcshrc.write("export NPCSH_EMBEDDING_MODEL='nomic-embed-text'\n")
102
- npcshrc.write("export NPCSH_VISION_PROVIDER='ollama'\n")
103
- npcshrc.write("export NPCSH_VISION_MODEL='llava7b'\n")
104
- npcshrc.write(
105
- "export NPCSH_IMAGE_GEN_MODEL='runwayml/stable-diffusion-v1-5'\n"
106
- )
107
-
108
- npcshrc.write("export NPCSH_IMAGE_GEN_PROVIDER='diffusers'\n")
109
- npcshrc.write(
110
- "export NPCSH_VIDEO_GEN_MODEL='runwayml/stable-diffusion-v1-5'\n"
111
- )
112
-
113
- npcshrc.write("export NPCSH_VIDEO_GEN_PROVIDER='diffusers'\n")
114
-
115
- npcshrc.write("export NPCSH_API_URL=''\n")
116
- npcshrc.write("export NPCSH_DB_PATH='~/npcsh_history.db'\n")
117
- npcshrc.write("export NPCSH_VECTOR_DB_PATH='~/npcsh_chroma.db'\n")
118
- npcshrc.write("export NPCSH_STREAM_OUTPUT=0")
119
- return npcshrc_path
120
-
121
-
122
- # Function to check and download NLTK data if necessary
123
- def ensure_nltk_punkt() -> None:
124
- """
125
- Function Description:
126
- This function ensures that the NLTK 'punkt' tokenizer is downloaded.
127
- Args:
128
- None
129
- Keyword Args:
130
- None
131
- Returns:
132
- None
133
- """
134
-
135
- try:
136
- nltk.data.find("tokenizers/punkt")
137
- except LookupError:
138
- print("Downloading NLTK 'punkt' tokenizer...")
139
- nltk.download("punkt")
140
-
141
-
142
- def load_all_files(
143
- directory: str, extensions: List[str] = None, depth: int = 1
144
- ) -> Dict[str, str]:
145
- """
146
- Function Description:
147
- This function loads all text files in a directory and its subdirectories.
148
- Args:
149
- directory: The directory to search.
150
- Keyword Args:
151
- extensions: A list of file extensions to include.
152
- depth: The depth of subdirectories to search.
153
- Returns:
154
- A dictionary with file paths as keys and file contents as values.
155
- """
156
- text_data = {}
157
- if depth < 1:
158
- return text_data # Reached the specified depth, stop recursion.
159
-
160
- if extensions is None:
161
- # Default to common text file extensions
162
- extensions = [
163
- ".txt",
164
- ".md",
165
- ".py",
166
- ".java",
167
- ".c",
168
- ".cpp",
169
- ".html",
170
- ".css",
171
- ".js",
172
- ".ts",
173
- ".tsx",
174
- ".npc",
175
- # Add more extensions if needed
176
- ]
177
-
178
- try:
179
- # List all entries in the directory
180
- entries = os.listdir(directory)
181
- except Exception as e:
182
- print(f"Could not list directory {directory}: {e}")
183
- return text_data
184
-
185
- for entry in entries:
186
- path = os.path.join(directory, entry)
187
- if os.path.isfile(path):
188
- if any(path.endswith(ext) for ext in extensions):
189
- try:
190
- with open(path, "r", encoding="utf-8", errors="ignore") as file:
191
- text_data[path] = file.read()
192
- except Exception as e:
193
- print(f"Could not read file {path}: {e}")
194
- elif os.path.isdir(path):
195
- # Recurse into subdirectories, decreasing depth by 1
196
- subdir_data = load_all_files(path, extensions, depth=depth - 1)
197
- text_data.update(subdir_data)
198
-
199
- return text_data
200
-
201
-
202
- def add_npcshrc_to_shell_config() -> None:
203
- """
204
- Function Description:
205
- This function adds the sourcing of the .npcshrc file to the user's shell configuration file.
206
- Args:
207
- None
208
- Keyword Args:
209
- None
210
- Returns:
211
- None
212
- """
213
-
214
- if os.getenv("NPCSH_INITIALIZED") is not None:
215
- return
216
- config_file = get_shell_config_file()
217
- npcshrc_line = "\n# Source NPCSH configuration\nif [ -f ~/.npcshrc ]; then\n . ~/.npcshrc\nfi\n"
218
-
219
- with open(config_file, "a+") as shell_config:
220
- shell_config.seek(0)
221
- content = shell_config.read()
222
- if "source ~/.npcshrc" not in content and ". ~/.npcshrc" not in content:
223
- shell_config.write(npcshrc_line)
224
- print(f"Added .npcshrc sourcing to {config_file}")
225
- else:
226
- print(f".npcshrc already sourced in {config_file}")
227
-
228
-
229
- def setup_npcsh_config() -> None:
230
- """
231
- Function Description:
232
- This function initializes the NPCSH configuration.
233
- Args:
234
- None
235
- Keyword Args:
236
- None
237
- Returns:
238
- None
239
- """
240
-
241
- ensure_npcshrc_exists()
242
- add_npcshrc_to_shell_config()
243
-
244
-
245
- def is_npcsh_initialized() -> bool:
246
- """
247
- Function Description:
248
- This function checks if the NPCSH initialization flag is set.
249
- Args:
250
- None
251
- Keyword Args:
252
- None
253
- Returns:
254
- A boolean indicating whether NPCSH is initialized.
255
- """
256
-
257
- return os.environ.get("NPCSH_INITIALIZED", None) == "1"
258
-
259
-
260
- def set_npcsh_initialized() -> None:
261
- """
262
- Function Description:
263
- This function sets the NPCSH initialization flag in the .npcshrc file.
264
- Args:
265
- None
266
- Keyword Args:
267
- None
268
- Returns:
269
-
270
- None
271
- """
272
-
273
- npcshrc_path = ensure_npcshrc_exists()
274
-
275
- with open(npcshrc_path, "r+") as npcshrc:
276
- content = npcshrc.read()
277
- if "export NPCSH_INITIALIZED=0" in content:
278
- content = content.replace(
279
- "export NPCSH_INITIALIZED=0", "export NPCSH_INITIALIZED=1"
280
- )
281
- npcshrc.seek(0)
282
- npcshrc.write(content)
283
- npcshrc.truncate()
284
-
285
- # Also set it for the current session
286
- os.environ["NPCSH_INITIALIZED"] = "1"
287
- print("NPCSH initialization flag set in .npcshrc")
288
-
289
-
290
- def get_directory_npcs(directory: str = None) -> List[str]:
291
- """
292
- Function Description:
293
- This function retrieves a list of valid NPCs from the database.
294
- Args:
295
- db_path: The path to the database file.
296
- Keyword Args:
297
- None
298
- Returns:
299
- A list of valid NPCs.
300
- """
301
- if directory is None:
302
- directory = os.path.expanduser("./npc_team")
303
- npcs = []
304
- for filename in os.listdir(directory):
305
- if filename.endswith(".npc"):
306
- npcs.append(filename[:-4])
307
- return npcs
308
-
309
-
310
- def get_db_npcs(db_path: str) -> List[str]:
311
- """
312
- Function Description:
313
- This function retrieves a list of valid NPCs from the database.
314
- Args:
315
- db_path: The path to the database file.
316
- Keyword Args:
317
- None
318
- Returns:
319
- A list of valid NPCs.
320
- """
321
- if "~" in db_path:
322
- db_path = os.path.expanduser(db_path)
323
- db_conn = sqlite3.connect(db_path)
324
- cursor = db_conn.cursor()
325
- cursor.execute("SELECT name FROM compiled_npcs")
326
- npcs = [row[0] for row in cursor.fetchall()]
327
- db_conn.close()
328
- return npcs
329
-
330
-
331
- def get_npc_path(npc_name: str, db_path: str) -> str:
332
- # First, check in project npc_team directory
333
- project_npc_team_dir = os.path.abspath("./npc_team")
334
- project_npc_path = os.path.join(project_npc_team_dir, f"{npc_name}.npc")
335
-
336
- # Then, check in global npc_team directory
337
- user_npc_team_dir = os.path.expanduser("~/.npcsh/npc_team")
338
- global_npc_path = os.path.join(user_npc_team_dir, f"{npc_name}.npc")
339
-
340
- # Check database for compiled NPCs
341
- try:
342
- with sqlite3.connect(db_path) as conn:
343
- cursor = conn.cursor()
344
- query = f"SELECT source_path FROM compiled_npcs WHERE name = '{npc_name}'"
345
- cursor.execute(query)
346
- result = cursor.fetchone()
347
- if result:
348
- return result[0]
349
-
350
- except Exception as e:
351
- try:
352
- with sqlite3.connect(db_path) as conn:
353
- cursor = conn.cursor()
354
- query = f"SELECT source_path FROM compiled_npcs WHERE name = {npc_name}"
355
- cursor.execute(query)
356
- result = cursor.fetchone()
357
- if result:
358
- return result[0]
359
- except Exception as e:
360
- print(f"Database query error: {e}")
361
-
362
- # Fallback to file paths
363
- if os.path.exists(project_npc_path):
364
- return project_npc_path
365
-
366
- if os.path.exists(global_npc_path):
367
- return global_npc_path
368
-
369
- raise ValueError(f"NPC file not found: {npc_name}")
370
-
371
-
372
- def initialize_base_npcs_if_needed(db_path: str) -> None:
373
- """
374
- Function Description:
375
- This function initializes the base NPCs if they are not already in the database.
376
- Args:
377
- db_path: The path to the database file.
378
- Keyword Args:
379
-
380
- None
381
- Returns:
382
- None
383
- """
384
-
385
- if is_npcsh_initialized():
386
- return
387
-
388
- conn = sqlite3.connect(db_path)
389
- cursor = conn.cursor()
390
-
391
- # Create the compiled_npcs table if it doesn't exist
392
- cursor.execute(
393
- """
394
- CREATE TABLE IF NOT EXISTS compiled_npcs (
395
- name TEXT PRIMARY KEY,
396
- source_path TEXT NOT NULL,
397
- compiled_content TEXT
398
- )
399
- """
400
- )
401
-
402
- # Get the path to the npc_team directory in the package
403
- package_dir = os.path.dirname(__file__)
404
- package_npc_team_dir = os.path.join(package_dir, "npc_team")
405
-
406
- # User's global npc_team directory
407
- user_npc_team_dir = os.path.expanduser("~/.npcsh/npc_team")
408
-
409
- user_tools_dir = os.path.join(user_npc_team_dir, "tools")
410
- user_templates_dir = os.path.join(user_npc_team_dir, "templates")
411
- os.makedirs(user_npc_team_dir, exist_ok=True)
412
- os.makedirs(user_tools_dir, exist_ok=True)
413
- os.makedirs(user_templates_dir, exist_ok=True)
414
- # Copy NPCs from package to user directory
415
- for filename in os.listdir(package_npc_team_dir):
416
- if filename.endswith(".npc"):
417
- source_path = os.path.join(package_npc_team_dir, filename)
418
- destination_path = os.path.join(user_npc_team_dir, filename)
419
- if not os.path.exists(destination_path) or file_has_changed(
420
- source_path, destination_path
421
- ):
422
- shutil.copy2(source_path, destination_path)
423
-
424
- # Copy tools from package to user directory
425
- package_tools_dir = os.path.join(package_npc_team_dir, "tools")
426
- if os.path.exists(package_tools_dir):
427
- for filename in os.listdir(package_tools_dir):
428
- if filename.endswith(".tool"):
429
- source_tool_path = os.path.join(package_tools_dir, filename)
430
- destination_tool_path = os.path.join(user_tools_dir, filename)
431
- if (not os.path.exists(destination_tool_path)) or file_has_changed(
432
- source_tool_path, destination_tool_path
433
- ):
434
- shutil.copy2(source_tool_path, destination_tool_path)
435
- print(f"Copied tool {filename} to {destination_tool_path}")
436
-
437
- templates = os.path.join(package_npc_team_dir, "templates")
438
- if os.path.exists(templates):
439
- for folder in os.listdir(templates):
440
- os.makedirs(os.path.join(user_templates_dir, folder), exist_ok=True)
441
- for file in os.listdir(os.path.join(templates, folder)):
442
- if file.endswith(".npc"):
443
- source_template_path = os.path.join(templates, folder, file)
444
-
445
- destination_template_path = os.path.join(
446
- user_templates_dir, folder, file
447
- )
448
- if not os.path.exists(
449
- destination_template_path
450
- ) or file_has_changed(
451
- source_template_path, destination_template_path
452
- ):
453
- shutil.copy2(source_template_path, destination_template_path)
454
- print(f"Copied template {file} to {destination_template_path}")
455
- conn.commit()
456
- conn.close()
457
- set_npcsh_initialized()
458
- add_npcshrc_to_shell_config()
459
-
460
-
461
- def file_has_changed(source_path: str, destination_path: str) -> bool:
462
- """
463
- Function Description:
464
- This function compares two files to determine if they are different.
465
- Args:
466
- source_path: The path to the source file.
467
- destination_path: The path to the destination file.
468
- Keyword Args:
469
- None
470
- Returns:
471
- A boolean indicating whether the files are different
472
- """
473
-
474
- # Compare file modification times or contents to decide whether to update the file
475
- return not filecmp.cmp(source_path, destination_path, shallow=False)
476
-
477
-
478
- def is_valid_npc(npc: str, db_path: str) -> bool:
479
- """
480
- Function Description:
481
- This function checks if an NPC is valid based on the database.
482
- Args:
483
- npc: The name of the NPC.
484
- db_path: The path to the database file.
485
- Keyword Args:
486
- None
487
- Returns:
488
- A boolean indicating whether the NPC is valid.
489
- """
490
-
491
- conn = sqlite3.connect(db_path)
492
- cursor = conn.cursor()
493
- cursor.execute("SELECT * FROM compiled_npcs WHERE name = ?", (npc,))
494
- result = cursor.fetchone()
495
- conn.close()
496
- return result is not None
497
-
498
-
499
- def execute_python(code: str) -> str:
500
- """
501
- Function Description:
502
- This function executes Python code and returns the output.
503
- Args:
504
- code: The Python code to execute.
505
- Keyword Args:
506
- None
507
- Returns:
508
- The output of the code execution.
509
- """
510
-
511
- try:
512
- result = subprocess.run(
513
- ["python", "-c", code], capture_output=True, text=True, timeout=30
514
- )
515
- return result.stdout if result.returncode == 0 else f"Error: {result.stderr}"
516
- except subprocess.TimeoutExpired:
517
- return "Error: Execution timed out"
518
-
519
-
520
- def execute_r(code: str) -> str:
521
- """
522
- Function Description:
523
- This function executes R code and returns the output.
524
- Args:
525
- code: The R code to execute.
526
- Keyword Args:
527
- None
528
- Returns:
529
- The output of the code execution.
530
- """
531
-
532
- try:
533
- with tempfile.NamedTemporaryFile(
534
- mode="w", suffix=".R", delete=False
535
- ) as temp_file:
536
- temp_file.write(code)
537
- temp_file_path = temp_file.name
538
-
539
- result = subprocess.run(
540
- ["Rscript", temp_file_path], capture_output=True, text=True, timeout=30
541
- )
542
- os.unlink(temp_file_path)
543
- return result.stdout if result.returncode == 0 else f"Error: {result.stderr}"
544
- except subprocess.TimeoutExpired:
545
- os.unlink(temp_file_path)
546
- return "Error: Execution timed out"
547
-
548
-
549
- def execute_sql(code: str) -> str:
550
- """
551
- Function Description:
552
- This function executes SQL code and returns the output.
553
- Args:
554
- code: The SQL code to execute.
555
- Keyword Args:
556
- None
557
- Returns:
558
- result: The output of the code execution.
559
- """
560
- # use pandas to run the sql
561
- try:
562
- result = pd.read_sql_query(code, con=sqlite3.connect("npcsh_history.db"))
563
- return result
564
- except Exception as e:
565
- return f"Error: {e}"
566
-
567
-
568
- def list_directory(args: List[str]) -> None:
569
- """
570
- Function Description:
571
- This function lists the contents of a directory.
572
- Args:
573
- args: The command arguments.
574
- Keyword Args:
575
- None
576
- Returns:
577
- None
578
- """
579
- directory = args[0] if args else "."
580
- try:
581
- files = os.listdir(directory)
582
- for f in files:
583
- print(f)
584
- except Exception as e:
585
- print(f"Error listing directory: {e}")
586
-
587
-
588
- def read_file(args: List[str]) -> None:
589
- """
590
- Function Description:
591
- This function reads the contents of a file.
592
- Args:
593
- args: The command arguments.
594
- Keyword Args:
595
- None
596
- Returns:
597
- None
598
- """
599
-
600
- if not args:
601
- print("Usage: /read <filename>")
602
- return
603
- filename = args[0]
604
- try:
605
- with open(filename, "r") as file:
606
- content = file.read()
607
- print(content)
608
- except Exception as e:
609
- print(f"Error reading file: {e}")
610
-
611
-
612
- import os
613
- import json
614
- from pathlib import Path
615
-
616
-
617
- def get_npcshrc_path_windows():
618
- return Path.home() / ".npcshrc"
619
-
620
-
621
- def read_rc_file_windows(path):
622
- """Read shell-style rc file"""
623
- config = {}
624
- if not path.exists():
625
- return config
626
-
627
- with open(path) as f:
628
- for line in f:
629
- line = line.strip()
630
- if line and not line.startswith("#"):
631
- # Match KEY='value' or KEY="value" format
632
- match = re.match(r'^([A-Z_]+)\s*=\s*[\'"](.*?)[\'"]$', line)
633
- if match:
634
- key, value = match.groups()
635
- config[key] = value
636
- return config
637
-
638
-
639
- def get_setting_windows(key, default=None):
640
- # Try environment variable first
641
- if env_value := os.getenv(key):
642
- return env_value
643
-
644
- # Fall back to .npcshrc file
645
- config = read_rc_file_windows(get_npcshrc_path())
646
- return config.get(key, default)