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