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/shell.py DELETED
@@ -1,524 +0,0 @@
1
- import os
2
- import sys
3
- import readline
4
- import atexit
5
- import re
6
- import pty
7
- import select
8
- import termios
9
- import tty
10
- import shlex
11
- import json
12
-
13
- from datetime import datetime
14
- from inspect import isgenerator
15
-
16
-
17
- # Third-party imports
18
- import pandas as pd
19
- import sqlite3
20
- import numpy as np
21
- from termcolor import colored
22
- from dotenv import load_dotenv
23
- import subprocess
24
- from typing import Dict, Any, List, Optional
25
-
26
-
27
- try:
28
- from sentence_transformers import SentenceTransformer
29
- except:
30
- print("Could not load the sentence-transformers package.")
31
- # Local imports
32
-
33
- from npcsh.npc_sysenv import (
34
- get_system_message,
35
- lookup_provider,
36
- NPCSH_STREAM_OUTPUT,
37
- NPCSH_CHAT_MODEL,
38
- NPCSH_CHAT_PROVIDER,
39
- NPCSH_API_URL,
40
- )
41
-
42
- from npcsh.command_history import (
43
- CommandHistory,
44
- start_new_conversation,
45
- save_conversation_message,
46
- save_attachment_to_message,
47
- )
48
- from npcsh.llm_funcs import (
49
- execute_llm_command,
50
- execute_llm_question,
51
- generate_image,
52
- check_llm_command,
53
- get_conversation,
54
- get_system_message,
55
- )
56
- from npcsh.search import rag_search, search_web
57
- from npcsh.helpers import (
58
- load_all_files,
59
- setup_npcsh_config,
60
- is_npcsh_initialized,
61
- initialize_base_npcs_if_needed,
62
- )
63
- from npcsh.shell_helpers import (
64
- complete, # For command completion
65
- readline_safe_prompt,
66
- get_multiline_input,
67
- setup_readline,
68
- execute_command,
69
- render_markdown,
70
- render_code_block,
71
- orange, # For colored prompt
72
- )
73
- from npcsh.npc_compiler import (
74
- NPCCompiler,
75
- load_tools_from_directory,
76
- NPC,
77
- initialize_npc_project,
78
- )
79
-
80
- import argparse
81
- from npcsh.serve import (
82
- start_flask_server,
83
- )
84
- import importlib.metadata # Python 3.8+
85
-
86
- # Fetch the version from the package metadata
87
- try:
88
- VERSION = importlib.metadata.version(
89
- "npcsh"
90
- ) # Replace "npcsh" with your package name
91
- except importlib.metadata.PackageNotFoundError:
92
- VERSION = "unknown" # Fallback if the package is not installed
93
-
94
-
95
- def main() -> None:
96
- """
97
- Main function for the npcsh shell and server.
98
- Starts either the Flask server or the interactive shell based on the argument provided.
99
- """
100
- # Set up argument parsing to handle 'serve' and regular commands
101
-
102
- check_old_par_name = os.environ.get("NPCSH_MODEL", None)
103
- if check_old_par_name is not None:
104
- # raise a deprecation warning
105
- print(
106
- """Deprecation Warning: NPCSH_MODEL and NPCSH_PROVIDER were deprecated in v0.3.5 in favor of NPCSH_CHAT_MODEL and NPCSH_CHAT_PROVIDER instead.\
107
- Please update your environment variables to use the new names.
108
- """
109
- )
110
-
111
- parser = argparse.ArgumentParser(description="npcsh CLI")
112
- parser.add_argument(
113
- "-v",
114
- "--version",
115
- action="version",
116
- version=f"npcsh version {VERSION}", # Use the dynamically fetched version
117
- )
118
- args = parser.parse_args()
119
-
120
- setup_npcsh_config()
121
- if "NPCSH_DB_PATH" in os.environ:
122
- db_path = os.path.expanduser(os.environ["NPCSH_DB_PATH"])
123
- else:
124
- db_path = os.path.expanduser("~/npcsh_history.db")
125
-
126
- command_history = CommandHistory(db_path)
127
- valid_commands = [
128
- "/compile",
129
- "/com",
130
- "/whisper",
131
- "/notes",
132
- "/data",
133
- "/cmd",
134
- "/command",
135
- "/set",
136
- "/sample",
137
- "/spool",
138
- "/sp",
139
- "/help",
140
- "/exit",
141
- "/quit",
142
- ]
143
-
144
- readline.set_completer_delims(" \t\n")
145
- readline.set_completer(complete)
146
- if sys.platform == "darwin":
147
- readline.parse_and_bind("bind ^I rl_complete")
148
- else:
149
- readline.parse_and_bind("tab: complete")
150
-
151
- # check if ./npc_team exists
152
- if os.path.exists("./npc_team"):
153
-
154
- npc_directory = os.path.abspath("./npc_team/")
155
- else:
156
- npc_directory = os.path.expanduser("~/.npcsh/npc_team/")
157
-
158
- npc_compiler = NPCCompiler(npc_directory, db_path)
159
-
160
- os.makedirs(npc_directory, exist_ok=True)
161
-
162
- # Compile all NPCs in the user's npc_team directory
163
- for filename in os.listdir(npc_directory):
164
- if filename.endswith(".npc"):
165
- npc_file_path = os.path.join(npc_directory, filename)
166
- npc_compiler.compile(npc_file_path)
167
-
168
- # Compile NPCs from project-specific npc_team directory
169
- if os.path.exists(npc_directory):
170
- for filename in os.listdir(npc_directory):
171
- if filename.endswith(".npc"):
172
- npc_file_path = os.path.join(npc_directory, filename)
173
- npc_compiler.compile(npc_file_path)
174
-
175
- if not is_npcsh_initialized():
176
- print("Initializing NPCSH...")
177
- initialize_base_npcs_if_needed(db_path)
178
- print(
179
- "NPCSH initialization complete. Please restart your terminal or run 'source ~/.npcshrc' for the changes to take effect."
180
- )
181
-
182
- history_file = setup_readline()
183
- atexit.register(readline.write_history_file, history_file)
184
- atexit.register(command_history.close)
185
- # make npcsh into ascii art
186
- from colorama import init
187
-
188
- init() # Initialize colorama for ANSI code support
189
- if sys.stdin.isatty():
190
-
191
- print(
192
- """
193
- Welcome to \033[1;94mnpc\033[0m\033[1;38;5;202msh\033[0m!
194
- \033[1;94m \033[0m\033[1;38;5;202m \\\\
195
- \033[1;94m _ __ _ __ ___ \033[0m\033[1;38;5;202m ___ | |___ \\\\
196
- \033[1;94m| '_ \ | '_ \ / __|\033[0m\033[1;38;5;202m/ __/ | |_ _| \\\\
197
- \033[1;94m| | | || |_) |( |__ \033[0m\033[1;38;5;202m\_ \ | | | | //
198
- \033[1;94m|_| |_|| .__/ \___|\033[0m\033[1;38;5;202m|___/ |_| |_| //
199
- \033[1;94m| | \033[0m\033[1;38;5;202m //
200
- \033[1;94m| |
201
- \033[1;94m|_|
202
-
203
- Begin by asking a question, issuing a bash command, or typing '/help' for more information.
204
- """
205
- )
206
-
207
- current_npc = None
208
- messages = None
209
- current_conversation_id = start_new_conversation()
210
-
211
- # --- Minimal Piped Input Handling ---
212
- if not sys.stdin.isatty():
213
- for line in sys.stdin:
214
- user_input = line.strip()
215
- if not user_input:
216
- continue # Skip empty lines
217
- if user_input.lower() in ["exit", "quit"]:
218
- print("Goodbye!")
219
- sys.exit(0)
220
- result = execute_command(
221
- user_input,
222
- db_path,
223
- npc_compiler,
224
- current_npc,
225
- model=NPCSH_CHAT_MODEL,
226
- provider=NPCSH_CHAT_PROVIDER,
227
- messages=messages,
228
- conversation_id=current_conversation_id,
229
- stream=NPCSH_STREAM_OUTPUT,
230
- api_url=NPCSH_API_URL,
231
- )
232
- messages = result.get("messages", messages)
233
- if "current_npc" in result:
234
- current_npc = result["current_npc"]
235
- output = result.get("output")
236
- conversation_id = result.get("conversation_id")
237
- model = result.get("model")
238
- provider = result.get("provider")
239
- npc = result.get("npc")
240
- messages = result.get("messages")
241
- current_path = result.get("current_path")
242
- attachments = result.get("attachments")
243
- npc_name = (
244
- npc.name
245
- if isinstance(npc, NPC)
246
- else npc if isinstance(npc, str) else None
247
- )
248
-
249
- save_conversation_message(
250
- command_history,
251
- conversation_id,
252
- "user",
253
- user_input,
254
- wd=current_path,
255
- model=model,
256
- provider=provider,
257
- npc=npc_name,
258
- attachments=attachments,
259
- )
260
- if NPCSH_STREAM_OUTPUT and (
261
- isgenerator(output)
262
- or (hasattr(output, "__iter__") and hasattr(output, "__next__"))
263
- ):
264
- str_output = ""
265
- in_code = False
266
- code_buffer = ""
267
- text_buffer = ""
268
-
269
- for chunk in output:
270
- # Get chunk content based on provider
271
- if provider == "anthropic":
272
- chunk_content = (
273
- chunk.delta.text
274
- if chunk.type == "content_block_delta"
275
- else None
276
- )
277
- elif provider in ["openai", "deepseek", "openai-like"]:
278
- chunk_content = "".join(
279
- c.delta.content for c in chunk.choices if c.delta.content
280
- )
281
- elif provider == "ollama":
282
- chunk_content = chunk["message"]["content"]
283
- else:
284
- continue
285
-
286
- if not chunk_content:
287
- continue
288
-
289
- str_output += chunk_content
290
-
291
- # Process chunk
292
- if "```" in chunk_content:
293
- parts = chunk_content.split("```")
294
-
295
- for i, part in enumerate(parts):
296
- if i == 0: # First part (before any backticks)
297
- if in_code:
298
- code_buffer += part
299
- else:
300
- print(part, end="")
301
- elif i % 2 == 1: # Inside a code block
302
- if not in_code: # Starting a new code block
303
- in_code = True
304
- code_buffer = part
305
- else: # Shouldn't happen but handle anyway
306
- code_buffer += part
307
- else: # Outside a code block
308
- if in_code: # Just finished a code block
309
- in_code = False
310
- # Render the code block
311
- render_code_block(code_buffer)
312
- code_buffer = ""
313
- print(part, end="")
314
- else:
315
- if in_code:
316
- code_buffer += chunk_content
317
- else:
318
- print(chunk_content, end="")
319
-
320
- # Handle any remaining code buffer
321
- if in_code and code_buffer:
322
- render_code_block(code_buffer)
323
-
324
- if str_output:
325
- output = str_output
326
- save_conversation_message(
327
- command_history,
328
- conversation_id,
329
- "assistant",
330
- output,
331
- wd=current_path,
332
- model=model,
333
- provider=provider,
334
- npc=npc_name,
335
- )
336
- sys.exit(0)
337
-
338
- while True:
339
- try:
340
- if current_npc:
341
- prompt = f"{colored(os.getcwd(), 'blue')}:{orange(current_npc.name)}> "
342
- else:
343
- prompt = f"{colored(os.getcwd(), 'blue')}:\033[1;94mnpc\033[0m\033[1;38;5;202msh\033[0m!> "
344
-
345
- prompt = readline_safe_prompt(prompt)
346
- user_input = get_multiline_input(prompt).strip()
347
-
348
- if user_input.lower() in ["exit", "quit"]:
349
- if current_npc:
350
- print(f"Exiting {current_npc.name} mode.")
351
- current_npc = None
352
- continue
353
- else:
354
- print("Goodbye!")
355
- break
356
- # print(current_npc, "current npc fore command execution")
357
- # Execute the command and capture the result
358
- result = execute_command(
359
- user_input,
360
- db_path,
361
- npc_compiler,
362
- current_npc=current_npc,
363
- model=NPCSH_CHAT_MODEL,
364
- provider=NPCSH_CHAT_PROVIDER,
365
- messages=messages,
366
- conversation_id=current_conversation_id,
367
- stream=NPCSH_STREAM_OUTPUT,
368
- api_url=NPCSH_API_URL,
369
- )
370
-
371
- messages = result.get("messages", messages)
372
-
373
- # need to adjust the output for the messages to all have
374
- # model, provider, npc, timestamp, role, content
375
- # also messages
376
-
377
- if "current_npc" in result:
378
-
379
- current_npc = result["current_npc"]
380
- output = result.get("output")
381
-
382
- conversation_id = result.get("conversation_id")
383
- model = result.get("model")
384
- provider = result.get("provider")
385
-
386
- messages = result.get("messages")
387
- current_path = result.get("current_path")
388
- attachments = result.get("attachments")
389
-
390
- if current_npc is not None:
391
- if isinstance(current_npc, NPC):
392
- npc_name = current_npc.name
393
- elif isinstance(current_npc, str):
394
- npc_name = current_npc
395
- else:
396
- npc_name = None
397
- message_id = save_conversation_message(
398
- command_history,
399
- conversation_id,
400
- "user",
401
- user_input,
402
- wd=current_path,
403
- model=model,
404
- provider=provider,
405
- npc=npc_name,
406
- attachments=attachments,
407
- )
408
-
409
- str_output = ""
410
- try:
411
- if NPCSH_STREAM_OUTPUT and hasattr(output, "__iter__"):
412
-
413
- buffer = ""
414
- in_code = False
415
- code_buffer = ""
416
-
417
- for chunk in output:
418
-
419
- chunk_content = "".join(
420
- c.delta.content for c in chunk.choices if c.delta.content
421
- )
422
- if not chunk_content:
423
- continue
424
-
425
- str_output += chunk_content
426
- # print(str_output, "str_output")
427
- # Process the content character by character
428
- for char in chunk_content:
429
- buffer += char
430
-
431
- # Check for triple backticks
432
- if buffer.endswith("```"):
433
- if not in_code:
434
- # Start of code block
435
- in_code = True
436
- # Print everything before the backticks
437
- print(buffer[:-3], end="")
438
- buffer = ""
439
- code_buffer = ""
440
- else:
441
- # End of code block
442
- in_code = False
443
- # Remove the backticks from the end of the buffer
444
- buffer = buffer[:-3]
445
- # Add buffer to code content and render
446
- code_buffer += buffer
447
-
448
- # Check for and strip language tag
449
- if (
450
- "\n" in code_buffer
451
- and code_buffer.index("\n") < 15
452
- ):
453
- first_line, rest = code_buffer.split("\n", 1)
454
- if (
455
- first_line.strip()
456
- and not "```" in first_line
457
- ):
458
- code_buffer = rest
459
-
460
- # Render the code block
461
- render_code_block(code_buffer)
462
-
463
- # Reset buffers
464
- buffer = ""
465
- code_buffer = ""
466
- elif in_code:
467
- # Just add to code buffer
468
- code_buffer += char
469
- if len(buffer) >= 3: # Keep buffer small while in code
470
- buffer = buffer[-3:]
471
- else:
472
- # Regular text - print if buffer gets too large
473
- if len(buffer) > 100:
474
- print(buffer[:-3], end="")
475
- buffer = buffer[
476
- -3:
477
- ] # Keep last 3 chars to check for backticks
478
-
479
- # Handle any remaining content
480
- if in_code:
481
- render_code_block(code_buffer)
482
- else:
483
- print(buffer, end="")
484
-
485
- if str_output:
486
- output = str_output
487
- except:
488
- output = None
489
-
490
- print("\n")
491
-
492
- if isinstance(output, str):
493
- save_conversation_message(
494
- command_history,
495
- conversation_id,
496
- "assistant",
497
- output,
498
- wd=current_path,
499
- model=model,
500
- provider=provider,
501
- npc=npc_name,
502
- )
503
-
504
- # if there are attachments in most recent user sent message, save them
505
- # save_attachment_to_message(command_history, message_id, # file_path, attachment_name, attachment_type)
506
-
507
- if (
508
- result["output"] is not None
509
- and not user_input.startswith("/")
510
- and not isinstance(result, dict)
511
- ):
512
- print("final", result)
513
-
514
- except (KeyboardInterrupt, EOFError):
515
- if current_npc:
516
- print(f"\nExiting {current_npc.name} mode.")
517
- current_npc = None
518
- else:
519
- print("\nGoodbye!")
520
- break
521
-
522
-
523
- if __name__ == "__main__":
524
- main()