npcsh 0.3.30__py3-none-any.whl → 0.3.31__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 (36) hide show
  1. npcsh/cli.py +30 -10
  2. npcsh/image.py +0 -2
  3. npcsh/npc_compiler.py +12 -0
  4. npcsh/npc_team/npcsh.ctx +8 -2
  5. npcsh/npc_team/tools/generic_search.tool +9 -1
  6. npcsh/search.py +15 -8
  7. npcsh/shell.py +87 -75
  8. npcsh/shell_helpers.py +24 -3
  9. {npcsh-0.3.30.data → npcsh-0.3.31.data}/data/npcsh/npc_team/generic_search.tool +9 -1
  10. {npcsh-0.3.30.data → npcsh-0.3.31.data}/data/npcsh/npc_team/npcsh.ctx +8 -2
  11. {npcsh-0.3.30.dist-info → npcsh-0.3.31.dist-info}/METADATA +12 -21
  12. {npcsh-0.3.30.dist-info → npcsh-0.3.31.dist-info}/RECORD +36 -36
  13. {npcsh-0.3.30.data → npcsh-0.3.31.data}/data/npcsh/npc_team/bash_executer.tool +0 -0
  14. {npcsh-0.3.30.data → npcsh-0.3.31.data}/data/npcsh/npc_team/calculator.tool +0 -0
  15. {npcsh-0.3.30.data → npcsh-0.3.31.data}/data/npcsh/npc_team/celona.npc +0 -0
  16. {npcsh-0.3.30.data → npcsh-0.3.31.data}/data/npcsh/npc_team/code_executor.tool +0 -0
  17. {npcsh-0.3.30.data → npcsh-0.3.31.data}/data/npcsh/npc_team/corca.npc +0 -0
  18. {npcsh-0.3.30.data → npcsh-0.3.31.data}/data/npcsh/npc_team/eriane.npc +0 -0
  19. {npcsh-0.3.30.data → npcsh-0.3.31.data}/data/npcsh/npc_team/foreman.npc +0 -0
  20. {npcsh-0.3.30.data → npcsh-0.3.31.data}/data/npcsh/npc_team/image_generation.tool +0 -0
  21. {npcsh-0.3.30.data → npcsh-0.3.31.data}/data/npcsh/npc_team/lineru.npc +0 -0
  22. {npcsh-0.3.30.data → npcsh-0.3.31.data}/data/npcsh/npc_team/local_search.tool +0 -0
  23. {npcsh-0.3.30.data → npcsh-0.3.31.data}/data/npcsh/npc_team/maurawa.npc +0 -0
  24. {npcsh-0.3.30.data → npcsh-0.3.31.data}/data/npcsh/npc_team/npcsh_executor.tool +0 -0
  25. {npcsh-0.3.30.data → npcsh-0.3.31.data}/data/npcsh/npc_team/raone.npc +0 -0
  26. {npcsh-0.3.30.data → npcsh-0.3.31.data}/data/npcsh/npc_team/screen_cap.tool +0 -0
  27. {npcsh-0.3.30.data → npcsh-0.3.31.data}/data/npcsh/npc_team/sibiji.npc +0 -0
  28. {npcsh-0.3.30.data → npcsh-0.3.31.data}/data/npcsh/npc_team/slean.npc +0 -0
  29. {npcsh-0.3.30.data → npcsh-0.3.31.data}/data/npcsh/npc_team/sql_executor.tool +0 -0
  30. {npcsh-0.3.30.data → npcsh-0.3.31.data}/data/npcsh/npc_team/test_pipeline.py +0 -0
  31. {npcsh-0.3.30.data → npcsh-0.3.31.data}/data/npcsh/npc_team/turnic.npc +0 -0
  32. {npcsh-0.3.30.data → npcsh-0.3.31.data}/data/npcsh/npc_team/welxor.npc +0 -0
  33. {npcsh-0.3.30.dist-info → npcsh-0.3.31.dist-info}/WHEEL +0 -0
  34. {npcsh-0.3.30.dist-info → npcsh-0.3.31.dist-info}/entry_points.txt +0 -0
  35. {npcsh-0.3.30.dist-info → npcsh-0.3.31.dist-info}/licenses/LICENSE +0 -0
  36. {npcsh-0.3.30.dist-info → npcsh-0.3.31.dist-info}/top_level.txt +0 -0
npcsh/cli.py CHANGED
@@ -33,6 +33,7 @@ from .llm_funcs import (
33
33
  get_stream,
34
34
  get_conversation,
35
35
  )
36
+ from .plonk import plonk, action_space
36
37
  from .search import search_web
37
38
  from .shell_helpers import *
38
39
  import os
@@ -54,10 +55,12 @@ def main():
54
55
  "assemble",
55
56
  "build",
56
57
  "compile",
58
+ "chat",
57
59
  "init",
58
60
  "new",
59
61
  "plonk",
60
62
  "sample",
63
+ "search",
61
64
  "select",
62
65
  "serve",
63
66
  "spool",
@@ -165,6 +168,10 @@ def main():
165
168
  "directory", nargs="?", default=".", help="Directory to build project in"
166
169
  )
167
170
 
171
+ # chat
172
+ chat_parser = subparsers.add_parser("chat", help="chat with an NPC")
173
+ chat_parser.add_argument("-n", "--npc_name", help="name of npc")
174
+
168
175
  # Compile command
169
176
  compile_parser = subparsers.add_parser("compile", help="Compile an NPC")
170
177
  compile_parser.add_argument("path", help="Path to NPC file")
@@ -300,7 +307,7 @@ def main():
300
307
 
301
308
  # Web search
302
309
  search_parser = subparsers.add_parser("search", help="search the web")
303
- search_parser.add_argument("query", help="search query")
310
+ search_parser.add_argument("--query", "-q", help="search query")
304
311
  search_parser.add_argument(
305
312
  "--search_provider",
306
313
  "-sp",
@@ -317,7 +324,7 @@ def main():
317
324
 
318
325
  # Voice chat
319
326
  whisper_parser = subparsers.add_parser("whisper", help="start voice chat")
320
- whisper_parser.add_argument("npc_name", help="name of the NPC to chat with")
327
+ whisper_parser.add_argument("-n", "--npc_name", help="name of the NPC to chat with")
321
328
 
322
329
  args = parser.parse_args()
323
330
 
@@ -367,6 +374,13 @@ def main():
367
374
  port=args.port if args.port else 5337,
368
375
  cors_origins=cors_origins,
369
376
  )
377
+ elif args.command == "chat":
378
+ npc_name = args.npc_name
379
+ npc_path = get_npc_path(npc_name, NPCSH_DB_PATH)
380
+ current_npc = load_npc_from_file(npc_path, sqlite3.connect(NPCSH_DB_PATH))
381
+ return enter_spool_mode(
382
+ model=args.model, provider=args.provider, npc=current_npc
383
+ )
370
384
 
371
385
  elif args.command == "init":
372
386
  if args.templates:
@@ -395,16 +409,18 @@ def main():
395
409
  )
396
410
 
397
411
  elif args.command == "compile":
398
- compile_npc(args.path)
412
+ npc_compiler = NPCCompiler(npc_directory, NPCSH_DB_PATH)
413
+ compiled = npc_compiler.compile(args.path)
414
+ print("NPC compiled to:", compiled)
399
415
 
400
416
  elif args.command == "plonk":
401
417
  task = args.task or args.spell
402
418
  npc_name = args.name
403
- run_plonk_task(
404
- task=task,
405
- npc_name=npc_name,
406
- model=args.model or NPCSH_REASONING_MODEL,
407
- provider=args.provider or NPCSH_REASONING_PROVIDER,
419
+ plonk(
420
+ task,
421
+ action_space,
422
+ model=args.model or NPCSH_CHAT_MODEL,
423
+ provider=args.provider or NPCSH_CHAT_PROVIDER,
408
424
  )
409
425
 
410
426
  elif args.command == "sample":
@@ -443,10 +459,14 @@ def main():
443
459
  model=args.model,
444
460
  provider=args.provider,
445
461
  )
446
- print(result)
462
+ print(result["output"])
447
463
 
448
464
  elif args.command == "whisper":
449
- start_whisper_chat(args.npc_name)
465
+ npc_name = args.npc_name
466
+ npc_path = get_npc_path(npc_name, NPCSH_DB_PATH)
467
+ current_npc = load_npc_from_file(npc_path, sqlite3.connect(NPCSH_DB_PATH))
468
+
469
+ enter_whisper_mode(npc=current_npc)
450
470
 
451
471
  elif args.command == "tool":
452
472
  result = invoke_tool(
npcsh/image.py CHANGED
@@ -283,8 +283,6 @@ def analyze_image(
283
283
  api_key=api_key,
284
284
  )
285
285
 
286
- print(response)
287
- # Add to command history *inside* the try block
288
286
  return response
289
287
 
290
288
  except Exception as e:
npcsh/npc_compiler.py CHANGED
@@ -501,6 +501,18 @@ class SilentUndefined(Undefined):
501
501
  return ""
502
502
 
503
503
 
504
+ class Context:
505
+ def __init__(self, context=None, mcp_servers=None, databases=None, files=None):
506
+ self.context = context
507
+ self.mcp_servers = mcp_servers
508
+ self.databases = databases
509
+ self.files = files
510
+
511
+ def load_context_file(self, path):
512
+ with open(path, "r") as f:
513
+ self.context = yaml.safe_load(f)
514
+
515
+
504
516
  class Tool:
505
517
  def __init__(self, tool_data: dict):
506
518
  if not tool_data or not isinstance(tool_data, dict):
npcsh/npc_team/npcsh.ctx CHANGED
@@ -1,5 +1,11 @@
1
- text: |
1
+ context: |
2
2
  The npcsh NPC team is devoted to providing a safe and helpful
3
3
  environment for users where they can work and be as successful as possible.
4
4
  npcsh is a command-line tool that makes it easy for users to harness
5
- the power of LLMs from a command line shell.
5
+ the power of LLMs from a command line shell.
6
+ databases:
7
+ - ~/npcsh_history.db
8
+ mcp_servers:
9
+ - /path/to/mcp/server.py
10
+ - @npm for server
11
+
@@ -2,13 +2,21 @@ tool_name: "internet_search"
2
2
  description: Searches the web for information based on a query in order to verify timiely details (e.g. current events) or to corroborate information in uncertain situations. Should be mainly only used when users specifically request a search, otherwise an LLMs basic knowledge should be sufficient.
3
3
  inputs:
4
4
  - query
5
+ - provider: ''
5
6
  steps:
6
7
  - engine: "python"
7
8
  code: |
8
9
  from npcsh.search import search_web
10
+ from npcsh.npc_sysenv import NPCSH_SEARCH_PROVIDER
9
11
  query = "{{ query }}"
12
+ provider = '{{ provider }}'
13
+ if provider.strip() != '':
14
+ results = search_web(query, num_results=5, provider = provider)
15
+ else:
16
+ results = search_web(query, num_results=5, provider = NPCSH_SEARCH_PROVIDER)
17
+
10
18
  print('QUERY in tool', query)
11
- results = search_web(query, num_results=5)
19
+ results = search_web(query, num_results=5, provider = NPCSH_SEARCH_PROVIDER)
12
20
  print('RESULTS in tool', results)
13
21
  - engine: "natural"
14
22
  code: |
npcsh/search.py CHANGED
@@ -5,6 +5,7 @@ import os
5
5
 
6
6
  from bs4 import BeautifulSoup
7
7
  from duckduckgo_search import DDGS
8
+ from duckduckgo_search.exceptions import DuckDuckGoSearchException
8
9
 
9
10
  try:
10
11
  from googlesearch import search
@@ -41,7 +42,6 @@ def search_perplexity(
41
42
  "max_tokens": max_tokens,
42
43
  "temperature": temperature,
43
44
  "top_p": top_p,
44
- "search_domain_filter": ["perplexity.ai"],
45
45
  "return_images": False,
46
46
  "return_related_questions": False,
47
47
  "search_recency_filter": "month",
@@ -58,6 +58,7 @@ def search_perplexity(
58
58
  # Make the POST request to the API
59
59
  response = requests.post(url, json=payload, headers=headers)
60
60
  response = json.loads(response.text)
61
+ print(response)
61
62
  return [response["choices"][0]["message"]["content"], response["citations"]]
62
63
 
63
64
 
@@ -89,13 +90,19 @@ def search_web(
89
90
 
90
91
  if provider == "duckduckgo":
91
92
  ddgs = DDGS()
92
- search_results = ddgs.text(query, max_results=num_results)
93
- print(search_results, type(search_results))
94
- urls = [r["href"] for r in search_results]
95
- results = [
96
- {"title": r["title"], "link": r["href"], "content": r["body"]}
97
- for r in search_results
98
- ]
93
+ try:
94
+ search_results = ddgs.text(query, max_results=num_results)
95
+ print(search_results, type(search_results))
96
+ urls = [r["href"] for r in search_results]
97
+ results = [
98
+ {"title": r["title"], "link": r["href"], "content": r["body"]}
99
+ for r in search_results
100
+ ]
101
+ except DuckDuckGoSearchException as e:
102
+ print("DuckDuckGo search failed: ", e)
103
+ urls = []
104
+ results = []
105
+
99
106
  else: # google
100
107
  urls = list(search(query, num_results=num_results))
101
108
  # google shit doesnt seem to be working anymore, apparently a lbock they made on browsers without js?
npcsh/shell.py CHANGED
@@ -407,88 +407,100 @@ def main() -> None:
407
407
  )
408
408
 
409
409
  str_output = ""
410
- if NPCSH_STREAM_OUTPUT and hasattr(output, "__iter__"):
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
+ if provider == "anthropic":
420
+ chunk_content = (
421
+ chunk.delta.text
422
+ if chunk.type == "content_block_delta"
423
+ else None
424
+ )
425
+ elif provider in ["openai", "deepseek", "openai-like"]:
426
+ chunk_content = "".join(
427
+ c.delta.content
428
+ for c in chunk.choices
429
+ if c.delta.content
430
+ )
431
+ elif provider == "ollama":
432
+ chunk_content = chunk["message"]["content"]
433
+ else:
434
+ continue
411
435
 
412
- buffer = ""
413
- in_code = False
414
- code_buffer = ""
436
+ if not chunk_content:
437
+ continue
415
438
 
416
- for chunk in output:
439
+ str_output += chunk_content
440
+ # print(str_output, "str_output")
441
+ # Process the content character by character
442
+ for char in chunk_content:
443
+ buffer += char
417
444
 
418
- if provider == "anthropic":
419
- chunk_content = (
420
- chunk.delta.text
421
- if chunk.type == "content_block_delta"
422
- else None
423
- )
424
- elif provider in ["openai", "deepseek", "openai-like"]:
425
- chunk_content = "".join(
426
- c.delta.content for c in chunk.choices if c.delta.content
427
- )
428
- elif provider == "ollama":
429
- chunk_content = chunk["message"]["content"]
430
- else:
431
- continue
445
+ # Check for triple backticks
446
+ if buffer.endswith("```"):
447
+ if not in_code:
448
+ # Start of code block
449
+ in_code = True
450
+ # Print everything before the backticks
451
+ print(buffer[:-3], end="")
452
+ buffer = ""
453
+ code_buffer = ""
454
+ else:
455
+ # End of code block
456
+ in_code = False
457
+ # Remove the backticks from the end of the buffer
458
+ buffer = buffer[:-3]
459
+ # Add buffer to code content and render
460
+ code_buffer += buffer
461
+
462
+ # Check for and strip language tag
463
+ if (
464
+ "\n" in code_buffer
465
+ and code_buffer.index("\n") < 15
466
+ ):
467
+ first_line, rest = code_buffer.split("\n", 1)
468
+ if (
469
+ first_line.strip()
470
+ and not "```" in first_line
471
+ ):
472
+ code_buffer = rest
432
473
 
433
- if not chunk_content:
434
- continue
474
+ # Render the code block
475
+ render_code_block(code_buffer)
435
476
 
436
- str_output += chunk_content
437
- # print(str_output, "str_output")
438
- # Process the content character by character
439
- for char in chunk_content:
440
- buffer += char
441
-
442
- # Check for triple backticks
443
- if buffer.endswith("```"):
444
- if not in_code:
445
- # Start of code block
446
- in_code = True
447
- # Print everything before the backticks
448
- print(buffer[:-3], end="")
449
- buffer = ""
450
- code_buffer = ""
477
+ # Reset buffers
478
+ buffer = ""
479
+ code_buffer = ""
480
+ elif in_code:
481
+ # Just add to code buffer
482
+ code_buffer += char
483
+ if len(buffer) >= 3: # Keep buffer small while in code
484
+ buffer = buffer[-3:]
451
485
  else:
452
- # End of code block
453
- in_code = False
454
- # Remove the backticks from the end of the buffer
455
- buffer = buffer[:-3]
456
- # Add buffer to code content and render
457
- code_buffer += buffer
458
-
459
- # Check for and strip language tag
460
- if "\n" in code_buffer and code_buffer.index("\n") < 15:
461
- first_line, rest = code_buffer.split("\n", 1)
462
- if first_line.strip() and not "```" in first_line:
463
- code_buffer = rest
464
-
465
- # Render the code block
466
- render_code_block(code_buffer)
467
-
468
- # Reset buffers
469
- buffer = ""
470
- code_buffer = ""
471
- elif in_code:
472
- # Just add to code buffer
473
- code_buffer += char
474
- if len(buffer) >= 3: # Keep buffer small while in code
475
- buffer = buffer[-3:]
476
- else:
477
- # Regular text - print if buffer gets too large
478
- if len(buffer) > 100:
479
- print(buffer[:-3], end="")
480
- buffer = buffer[
481
- -3:
482
- ] # Keep last 3 chars to check for backticks
483
-
484
- # Handle any remaining content
485
- if in_code:
486
- render_code_block(code_buffer)
487
- else:
488
- print(buffer, end="")
486
+ # Regular text - print if buffer gets too large
487
+ if len(buffer) > 100:
488
+ print(buffer[:-3], end="")
489
+ buffer = buffer[
490
+ -3:
491
+ ] # Keep last 3 chars to check for backticks
492
+
493
+ # Handle any remaining content
494
+ if in_code:
495
+ render_code_block(code_buffer)
496
+ else:
497
+ print(buffer, end="")
498
+
499
+ if str_output:
500
+ output = str_output
501
+ except:
502
+ output = None
489
503
 
490
- if str_output:
491
- output = str_output
492
504
  print("\n")
493
505
 
494
506
  if isinstance(output, str):
npcsh/shell_helpers.py CHANGED
@@ -1631,6 +1631,9 @@ def ots(
1631
1631
  output = analyze_image(
1632
1632
  user_prompt, file_path, filename, npc=npc, model=model, provider=provider
1633
1633
  )
1634
+ messages = [
1635
+ {"role": "user", "content": user_prompt},
1636
+ ]
1634
1637
 
1635
1638
  else:
1636
1639
  output = capture_screenshot(npc=npc)
@@ -1651,12 +1654,15 @@ def ots(
1651
1654
  # messages = output["messages"]
1652
1655
 
1653
1656
  output = output["response"]
1654
-
1657
+ messages = [
1658
+ {"role": "user", "content": user_prompt},
1659
+ ]
1655
1660
  if output:
1656
1661
  if isinstance(output, dict) and "filename" in output:
1657
1662
  message = f"Screenshot captured: {output['filename']}\nFull path: {output['file_path']}\nLLM-ready data available."
1658
1663
  else: # This handles both LLM responses and error messages (both strings)
1659
1664
  message = output
1665
+ messages.append({"role": "assistant", "content": message})
1660
1666
  return {"messages": messages, "output": message} # Return the message
1661
1667
  else: # Handle the case where capture_screenshot returns None
1662
1668
  print("Screenshot capture failed.")
@@ -2042,6 +2048,18 @@ def execute_slash_command(
2042
2048
  device = part.split("=")[1]
2043
2049
  if part.startswith("rag_similarity_threshold="):
2044
2050
  rag_similarity_threshold = float(part.split("=")[1])
2051
+ if part.startswith("model="):
2052
+ model = part.split("=")[1]
2053
+
2054
+ if part.startswith("provider="):
2055
+ provider = part.split("=")[1]
2056
+ if part.startswith("api_url="):
2057
+ api_url = part.split("=")[1]
2058
+ if part.startswith("api_key="):
2059
+ api_key = part.split("=")[1]
2060
+
2061
+ # load the npc properly
2062
+
2045
2063
  match = re.search(r"files=\s*\[(.*?)\]", command)
2046
2064
  files = []
2047
2065
  if match:
@@ -2066,10 +2084,11 @@ def execute_slash_command(
2066
2084
 
2067
2085
  print(f"Reattached to previous conversation:\n\n")
2068
2086
  output = enter_spool_mode(
2069
- command_history,
2070
2087
  inherit_last,
2071
2088
  files=files,
2072
2089
  npc=npc,
2090
+ model=model,
2091
+ provider=provider,
2073
2092
  rag_similarity_threshold=rag_similarity_threshold,
2074
2093
  device=device,
2075
2094
  messages=spool_context,
@@ -2082,7 +2101,6 @@ def execute_slash_command(
2082
2101
  return {"messages": [], "output": "No previous conversation found."}
2083
2102
 
2084
2103
  output = enter_spool_mode(
2085
- command_history,
2086
2104
  inherit_last,
2087
2105
  files=files,
2088
2106
  npc=npc,
@@ -2367,11 +2385,13 @@ def execute_command(
2367
2385
  valid_npcs = get_db_npcs(db_path)
2368
2386
 
2369
2387
  npc_name = get_npc_from_command(command)
2388
+
2370
2389
  if npc_name is None:
2371
2390
  npc_name = "sibiji" # Default NPC
2372
2391
  npc_path = get_npc_path(npc_name, db_path)
2373
2392
 
2374
2393
  npc = load_npc_from_file(npc_path, db_conn)
2394
+ current_npc = npc
2375
2395
  else:
2376
2396
  valid_npcs = [current_npc]
2377
2397
  npc = current_npc
@@ -3163,6 +3183,7 @@ def enter_spool_mode(
3163
3183
  Dict : The messages and output.
3164
3184
 
3165
3185
  """
3186
+
3166
3187
  command_history = CommandHistory()
3167
3188
  npc_info = f" (NPC: {npc.name})" if npc else ""
3168
3189
  print(f"Entering spool mode{npc_info}. Type '/sq' to exit spool mode.")
@@ -2,13 +2,21 @@ tool_name: "internet_search"
2
2
  description: Searches the web for information based on a query in order to verify timiely details (e.g. current events) or to corroborate information in uncertain situations. Should be mainly only used when users specifically request a search, otherwise an LLMs basic knowledge should be sufficient.
3
3
  inputs:
4
4
  - query
5
+ - provider: ''
5
6
  steps:
6
7
  - engine: "python"
7
8
  code: |
8
9
  from npcsh.search import search_web
10
+ from npcsh.npc_sysenv import NPCSH_SEARCH_PROVIDER
9
11
  query = "{{ query }}"
12
+ provider = '{{ provider }}'
13
+ if provider.strip() != '':
14
+ results = search_web(query, num_results=5, provider = provider)
15
+ else:
16
+ results = search_web(query, num_results=5, provider = NPCSH_SEARCH_PROVIDER)
17
+
10
18
  print('QUERY in tool', query)
11
- results = search_web(query, num_results=5)
19
+ results = search_web(query, num_results=5, provider = NPCSH_SEARCH_PROVIDER)
12
20
  print('RESULTS in tool', results)
13
21
  - engine: "natural"
14
22
  code: |
@@ -1,5 +1,11 @@
1
- text: |
1
+ context: |
2
2
  The npcsh NPC team is devoted to providing a safe and helpful
3
3
  environment for users where they can work and be as successful as possible.
4
4
  npcsh is a command-line tool that makes it easy for users to harness
5
- the power of LLMs from a command line shell.
5
+ the power of LLMs from a command line shell.
6
+ databases:
7
+ - ~/npcsh_history.db
8
+ mcp_servers:
9
+ - /path/to/mcp/server.py
10
+ - @npm for server
11
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: npcsh
3
- Version: 0.3.30
3
+ Version: 0.3.31
4
4
  Summary: npcsh is a command line tool for integrating LLMs into everyday workflows and for orchestrating teams of NPCs.
5
5
  Home-page: https://github.com/cagostino/npcsh
6
6
  Author: Christopher Agostino
@@ -112,22 +112,23 @@ Interested to stay in the loop and to hear the latest and greatest about `npcsh`
112
112
  ## TLDR Cheat Sheet
113
113
  Users can take advantage of `npcsh` through its custom shell or through a command-line interface (CLI) tool. Below is a cheat sheet that shows how to use `npcsh` commands in both the shell and the CLI. For the npcsh commands to work, one must activate `npcsh` by typing it in a shell.
114
114
 
115
+
116
+
117
+
115
118
  | Task | npc CLI | npcsh |
116
119
  |----------|----------|----------|
117
120
  | Ask a generic question | npc 'prompt' | 'prompt' |
118
121
  | Compile an NPC | npc compile /path/to/npc.npc | /compile /path/to/npc.npc |
119
122
  | Computer use | npc plonk -n 'npc_name' -sp 'task for plonk to carry out '| /plonk -n 'npc_name' -sp 'task for plonk to carry out ' |
120
123
  | Conjure an NPC team from context and templates | npc init -t 'template1, template2' -ctx 'context' | /conjure -t 'template1, 'template2' -ctx 'context' |
121
- | Enter a chat with an NPC (NPC needs to be compiled first) | npc npc_name | /npc_name |
124
+ | Enter a chat with an NPC (NPC needs to be compiled first) | npc chat -n npc_name | /spool npc=<npc_name> |
122
125
  | Generate image | npc vixynt 'prompt' | /vixynt prompt |
123
126
  | Get a sample LLM response | npc sample 'prompt' | /sample prompt for llm |
124
- | Invoke a tool | npc tool {tool_name} -args --flags | /tool_name -args --flags |
125
- | Search locally | npc tool local_search -args --flags | /local_search -args --flags |
126
127
  | Search for a term in the npcsh_db only in conversations with a specific npc | npc rag -n 'npc_name' -f 'filename' -q 'query' | /rag -n 'npc_name' -f 'filename' -q 'query' |
127
- | Search the web | npc search -p provider 'query' | /search -p provider 'query' |
128
+ | Search the web | npc search -q "cal golden bears football schedule" -sp perplexity | /search -p perplexity 'cal bears football schedule' |
128
129
  | Serve an NPC team | npc serve --port 5337 --cors='http://localhost:5137/' | /serve --port 5337 --cors='http://localhost:5137/' |
129
130
  | Screenshot analysis | npc ots | /ots |
130
- | Voice Chat | npc whisper 'npc_name' | /whisper |
131
+ | Voice Chat | npc whisper -n 'npc_name' | /whisper |
131
132
 
132
133
 
133
134
  ## Python Examples
@@ -725,19 +726,6 @@ The code in the visible section of your VS Code window appears to be a script fo
725
726
  In summary, this code automates the process of capturing a screenshot, saving it with a unique filename, and analyzing that image for specific content or patterns.
726
727
 
727
728
 
728
- ```
729
-
730
- ```npcsh
731
- npcsh> What is the biggest file in my current folder?
732
-
733
- LLM suggests the following bash command: ls -S | head -n 1
734
-
735
- Running command: ls -S | head -n 1
736
-
737
- Command executed with output: image_20241111_000033.png
738
-
739
- I ran the command ls -S | head -n 1 in your current folder. This command sorts all files by size in descending order and then selects the first entry, which represents the largest file. The result of this operation shows that the biggest file in your current folder is image_20241111_000033.png.
740
-
741
729
  ```
742
730
 
743
731
  ```npcsh
@@ -869,7 +857,7 @@ and then the associated image :
869
857
  An important facet that makes `npcsh` so powerful is the ability to pipe outputs from one tool call to another. This allows for the chaining of commands and the creation of complex workflows. For example, you can use the output of a search to generate an image, or you can use the output of an image analysis to generate a report. Here is an example of how this might look in practice:
870
858
  ```npcsh
871
859
  npcsh> what is the gdp of russia in 2024? | /vixynt 'generate an image that contains {0}'
872
-
860
+ ```
873
861
  ### Executing Bash Commands
874
862
  You can execute bash commands directly within npcsh. The LLM can also generate and execute bash commands based on your natural language requests.
875
863
  For example:
@@ -1167,7 +1155,10 @@ Search can be accomplished through the `/search` macro. You can specify the prov
1167
1155
  you must set a perplexity api key as an environment variable as described above. The default provider is duckduckgo.
1168
1156
 
1169
1157
  NOTE: while google is an available search engine, they recently implemented changes (early 2025) that make the python google search package no longer as reliable.
1170
- For now, we will use duckduckgo and revisit this issue when other more critical aspects are handled.
1158
+ Duckduckgo's search toool also givies rate limit errors often, so until a more robust
1159
+ solution is implemented for it, Perplexity's will be the most reliable.
1160
+
1161
+
1171
1162
 
1172
1163
 
1173
1164
  ```npcsh
@@ -1,32 +1,32 @@
1
1
  npcsh/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  npcsh/audio.py,sha256=DsRJ4Fq30kuq820dBwNy5otiZ7IFaRLSXYc1RZ4qlOk,5938
3
- npcsh/cli.py,sha256=Q1Pr3NllVqiWMGt8-aoYV4P-3pofKut9gvHjpTVjA6c,16270
3
+ npcsh/cli.py,sha256=2lKzc5bvPvvY_Er1_8JL3Fjbn-K_7Swj8Y1Z5nXDxB8,17118
4
4
  npcsh/command_history.py,sha256=epzP6okq03Jk1FpnC_Vr-yZPloXgmv0JcVy4h1RcVVI,17131
5
5
  npcsh/conversation.py,sha256=h-OfKwP88o9YYzQW1lx-dguN_lxIVTWxkmpJBLt2_1Q,8953
6
6
  npcsh/data_models.py,sha256=pUoSQtHEWpQUdgd2TRpPYB6mUmEtyaPgKPHuKtU3MW4,721
7
7
  npcsh/dataframes.py,sha256=OPVtc2q976R8c93HkE6tIl9hFOsDgwaFQEKQQAmNC1g,5263
8
8
  npcsh/embeddings.py,sha256=CJMivZZZKUH2Ck2VK9LWKgjVRgpbzd32OabM3czKiFQ,5547
9
9
  npcsh/helpers.py,sha256=aiK6kzf1jEYTHFssSxMOhPWDIcRvE0jXyrxWqh0coek,18992
10
- npcsh/image.py,sha256=nVnVsd0yqmUoyoyJWqbPLlEmjtFctNnpkiKZLdTSVIg,10533
10
+ npcsh/image.py,sha256=7mNDmtcOGPqkgahdf3F1rbViTwgEvi2PlPeFuSd6Dvo,10429
11
11
  npcsh/image_gen.py,sha256=PZQfFBtyXQuxfs1x2mJGL4RkudnKdzZp5Xem9gSevG0,2047
12
12
  npcsh/knowledge_graph.py,sha256=YIE0SJmUUfYrn1GqG6L7lWG0dIsQBun7A5CeA86PO6o,31442
13
13
  npcsh/llm_funcs.py,sha256=lhjhyua11UyKE5mQLJ7ziDtSNVelHKBFqr0QSKrSAYc,68254
14
14
  npcsh/load_data.py,sha256=Vh6YGxFVGWBMcn4cDrIgy8sC7QGCrWk0niJyR3l-k9U,1967
15
15
  npcsh/main.py,sha256=rpf_2ysx3cR3eHsrvZApprJ-3D3-OrWcJ15bM1bc97I,81
16
16
  npcsh/model_runner.py,sha256=riS6Hx3M7mj5erMm7OwBA8yufXYseVEbMYTRSfaDh2Y,6427
17
- npcsh/npc_compiler.py,sha256=ZSn181_7SLdCRLC-VsaDofxCtsI_RaJ5e6jBpnhd3tQ,104931
17
+ npcsh/npc_compiler.py,sha256=Dy5MJG-NHwNayZKiMA1oFEkPPJ75Hnxvenf09x53Nec,105284
18
18
  npcsh/npc_sysenv.py,sha256=g5LPYo8g6jlKd22fWVGghanLCr7tqjxytKvFbu0k-C0,11505
19
19
  npcsh/plonk.py,sha256=ewdkX6K1V9kLFkrNsQ5oGXLiuFaLev9mxXBY-B0PKus,9926
20
20
  npcsh/response.py,sha256=DFh6uoIw06SqPqKGv9DGHzoltprUHJSz6ZxgFBZRzX8,22478
21
- npcsh/search.py,sha256=K3AcYlefm_YNWQO_Yq5kTIRFKIIN3xX70CC3z038ox0,8605
21
+ npcsh/search.py,sha256=hIgqb_ymEfZMPLt5p-EZzLW_kaESmvlCyqKwB5ieFWI,8828
22
22
  npcsh/serve.py,sha256=Zy47IdaGCt5ziGnQ5KHTQH1K7xXyo7trwUMVDOLNxvU,48246
23
- npcsh/shell.py,sha256=_zQAp8jZuyDDYH4fwZxORrT1wnHhL85OsksC-t9xdtQ,18189
24
- npcsh/shell_helpers.py,sha256=df1HUeZSJUBfVK-wNkS6TJlwwoGDHXmaXKbFOR1FXFk,115398
23
+ npcsh/shell.py,sha256=BElVJf9cFj-AG2hCvmiavwDdZzsxLXP5XxMylJV17WI,18857
24
+ npcsh/shell_helpers.py,sha256=KaIegrlVS4fd-z1m9weP3iPkaIJgZgCdpOeNgmCGkec,116069
25
25
  npcsh/stream.py,sha256=gEwanrb5g4Fmu10fVN-3Gu_i434GWtE6zNZrhjQJ6EA,21995
26
26
  npcsh/video.py,sha256=Fv9Sii6LIEOI6D_1eoEu7DA8Es3mUYxEPcX3dac2Lt0,1935
27
27
  npcsh/npc_team/corca.npc,sha256=9qs7922thBESU4r5GRygqAjvg9zvhQyMYqqyb4wwSew,662
28
28
  npcsh/npc_team/foreman.npc,sha256=WqB8jLfBToGmr8c1vip1KOnTHxfXlGXwDUGnZoDMQr0,327
29
- npcsh/npc_team/npcsh.ctx,sha256=VOd7omCBo_764gKCYuHxJcyVc61oC5YjB7rnCbDhnYU,275
29
+ npcsh/npc_team/npcsh.ctx,sha256=cJW1HXtTihQ970iF_53rsyysGFa-E6u3BjAHGb1tMPI,380
30
30
  npcsh/npc_team/sibiji.npc,sha256=MJZHU9xXmvUbZvwpX1wWinvkrwYiKm1J63t37l0EYGE,202
31
31
  npcsh/npc_team/assembly_lines/test_pipeline.py,sha256=GKIcqw0fXDHsUDfMvu7GTj5cfPnqs7aX5xxiKPs2xCc,5657
32
32
  npcsh/npc_team/templates/analytics/celona.npc,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -40,37 +40,37 @@ npcsh/npc_team/templates/software/welxor.npc,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRk
40
40
  npcsh/npc_team/tools/bash_executer.tool,sha256=Myn87qJ6u-oWzZLZkd6TjxXE_TT-z3oGh5Wzs2TcD3I,836
41
41
  npcsh/npc_team/tools/calculator.tool,sha256=ZKmQ0VusuJj8Ib5MDqC8MTDaqWIZCxzpazWPVkYZqYc,197
42
42
  npcsh/npc_team/tools/code_executor.tool,sha256=L0gerbPkDgykgwvto_aKC8oUOrfv5lF2DhE51JEUFHM,511
43
- npcsh/npc_team/tools/generic_search.tool,sha256=sYA4aUuZm84vpx-5tNi6ADq9ywHaj_YfLt6PI0ZblUo,745
43
+ npcsh/npc_team/tools/generic_search.tool,sha256=6RFEZJK6HmEbuvpSnQctUGxchmQYjAwQlMcJGzu_OS4,1094
44
44
  npcsh/npc_team/tools/image_generation.tool,sha256=CaTkdjxWLFtMAghPvZnToMSwHbMQVusojhd9R9jybmI,577
45
45
  npcsh/npc_team/tools/local_search.tool,sha256=g9Hc_Xx08fc6lu1IHvdwYU_18KxcOoHDwvIAfrGmn3U,6852
46
46
  npcsh/npc_team/tools/npcsh_executor.tool,sha256=mavPowr8qXyPUuqRGqb5u1L8motyFoAyb4Xni4AjlFg,178
47
47
  npcsh/npc_team/tools/screen_cap.tool,sha256=v7l54PWWdgszdd-n_DFqI9nyMlBSeYeNIfQsdFYSZ_4,1389
48
48
  npcsh/npc_team/tools/sql_executor.tool,sha256=kEgxpb_9QUJpj8MEbzJY-isATG6Pi3KfVuffpwaoESM,808
49
- npcsh-0.3.30.data/data/npcsh/npc_team/bash_executer.tool,sha256=Myn87qJ6u-oWzZLZkd6TjxXE_TT-z3oGh5Wzs2TcD3I,836
50
- npcsh-0.3.30.data/data/npcsh/npc_team/calculator.tool,sha256=ZKmQ0VusuJj8Ib5MDqC8MTDaqWIZCxzpazWPVkYZqYc,197
51
- npcsh-0.3.30.data/data/npcsh/npc_team/celona.npc,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
- npcsh-0.3.30.data/data/npcsh/npc_team/code_executor.tool,sha256=L0gerbPkDgykgwvto_aKC8oUOrfv5lF2DhE51JEUFHM,511
53
- npcsh-0.3.30.data/data/npcsh/npc_team/corca.npc,sha256=9qs7922thBESU4r5GRygqAjvg9zvhQyMYqqyb4wwSew,662
54
- npcsh-0.3.30.data/data/npcsh/npc_team/eriane.npc,sha256=5z6L-RjEouEp06SLOzkQoOCEi0eb1K-CxVnvyIbNK3g,299
55
- npcsh-0.3.30.data/data/npcsh/npc_team/foreman.npc,sha256=WqB8jLfBToGmr8c1vip1KOnTHxfXlGXwDUGnZoDMQr0,327
56
- npcsh-0.3.30.data/data/npcsh/npc_team/generic_search.tool,sha256=sYA4aUuZm84vpx-5tNi6ADq9ywHaj_YfLt6PI0ZblUo,745
57
- npcsh-0.3.30.data/data/npcsh/npc_team/image_generation.tool,sha256=CaTkdjxWLFtMAghPvZnToMSwHbMQVusojhd9R9jybmI,577
58
- npcsh-0.3.30.data/data/npcsh/npc_team/lineru.npc,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
59
- npcsh-0.3.30.data/data/npcsh/npc_team/local_search.tool,sha256=g9Hc_Xx08fc6lu1IHvdwYU_18KxcOoHDwvIAfrGmn3U,6852
60
- npcsh-0.3.30.data/data/npcsh/npc_team/maurawa.npc,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
61
- npcsh-0.3.30.data/data/npcsh/npc_team/npcsh.ctx,sha256=VOd7omCBo_764gKCYuHxJcyVc61oC5YjB7rnCbDhnYU,275
62
- npcsh-0.3.30.data/data/npcsh/npc_team/npcsh_executor.tool,sha256=mavPowr8qXyPUuqRGqb5u1L8motyFoAyb4Xni4AjlFg,178
63
- npcsh-0.3.30.data/data/npcsh/npc_team/raone.npc,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
64
- npcsh-0.3.30.data/data/npcsh/npc_team/screen_cap.tool,sha256=v7l54PWWdgszdd-n_DFqI9nyMlBSeYeNIfQsdFYSZ_4,1389
65
- npcsh-0.3.30.data/data/npcsh/npc_team/sibiji.npc,sha256=MJZHU9xXmvUbZvwpX1wWinvkrwYiKm1J63t37l0EYGE,202
66
- npcsh-0.3.30.data/data/npcsh/npc_team/slean.npc,sha256=to3-d7qWMzhrYAeXalzNqVdt_3wROFGEfhprVXDttos,326
67
- npcsh-0.3.30.data/data/npcsh/npc_team/sql_executor.tool,sha256=kEgxpb_9QUJpj8MEbzJY-isATG6Pi3KfVuffpwaoESM,808
68
- npcsh-0.3.30.data/data/npcsh/npc_team/test_pipeline.py,sha256=GKIcqw0fXDHsUDfMvu7GTj5cfPnqs7aX5xxiKPs2xCc,5657
69
- npcsh-0.3.30.data/data/npcsh/npc_team/turnic.npc,sha256=odTFzQTN01-xaWXvjoC698htaFi6mvrzfKMAob8Yqb0,335
70
- npcsh-0.3.30.data/data/npcsh/npc_team/welxor.npc,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
71
- npcsh-0.3.30.dist-info/licenses/LICENSE,sha256=j0YPvce7Ng9e32zYOu0EmXjXeJ0Nwawd0RA3uSGGH4E,1070
72
- npcsh-0.3.30.dist-info/METADATA,sha256=oDq8RX-geEfX-L6ZbsPO0jwiThcsmikvTJGotqgt5E8,83180
73
- npcsh-0.3.30.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
74
- npcsh-0.3.30.dist-info/entry_points.txt,sha256=Y2rAM_m1er_Effxc0DXtGh36sC1FOUfefqGAt6vEte0,64
75
- npcsh-0.3.30.dist-info/top_level.txt,sha256=kHSNgKMCkfjV95-DH0YSp1LLBi0HXdF3w57j7MQON3E,6
76
- npcsh-0.3.30.dist-info/RECORD,,
49
+ npcsh-0.3.31.data/data/npcsh/npc_team/bash_executer.tool,sha256=Myn87qJ6u-oWzZLZkd6TjxXE_TT-z3oGh5Wzs2TcD3I,836
50
+ npcsh-0.3.31.data/data/npcsh/npc_team/calculator.tool,sha256=ZKmQ0VusuJj8Ib5MDqC8MTDaqWIZCxzpazWPVkYZqYc,197
51
+ npcsh-0.3.31.data/data/npcsh/npc_team/celona.npc,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
+ npcsh-0.3.31.data/data/npcsh/npc_team/code_executor.tool,sha256=L0gerbPkDgykgwvto_aKC8oUOrfv5lF2DhE51JEUFHM,511
53
+ npcsh-0.3.31.data/data/npcsh/npc_team/corca.npc,sha256=9qs7922thBESU4r5GRygqAjvg9zvhQyMYqqyb4wwSew,662
54
+ npcsh-0.3.31.data/data/npcsh/npc_team/eriane.npc,sha256=5z6L-RjEouEp06SLOzkQoOCEi0eb1K-CxVnvyIbNK3g,299
55
+ npcsh-0.3.31.data/data/npcsh/npc_team/foreman.npc,sha256=WqB8jLfBToGmr8c1vip1KOnTHxfXlGXwDUGnZoDMQr0,327
56
+ npcsh-0.3.31.data/data/npcsh/npc_team/generic_search.tool,sha256=6RFEZJK6HmEbuvpSnQctUGxchmQYjAwQlMcJGzu_OS4,1094
57
+ npcsh-0.3.31.data/data/npcsh/npc_team/image_generation.tool,sha256=CaTkdjxWLFtMAghPvZnToMSwHbMQVusojhd9R9jybmI,577
58
+ npcsh-0.3.31.data/data/npcsh/npc_team/lineru.npc,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
59
+ npcsh-0.3.31.data/data/npcsh/npc_team/local_search.tool,sha256=g9Hc_Xx08fc6lu1IHvdwYU_18KxcOoHDwvIAfrGmn3U,6852
60
+ npcsh-0.3.31.data/data/npcsh/npc_team/maurawa.npc,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
61
+ npcsh-0.3.31.data/data/npcsh/npc_team/npcsh.ctx,sha256=cJW1HXtTihQ970iF_53rsyysGFa-E6u3BjAHGb1tMPI,380
62
+ npcsh-0.3.31.data/data/npcsh/npc_team/npcsh_executor.tool,sha256=mavPowr8qXyPUuqRGqb5u1L8motyFoAyb4Xni4AjlFg,178
63
+ npcsh-0.3.31.data/data/npcsh/npc_team/raone.npc,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
64
+ npcsh-0.3.31.data/data/npcsh/npc_team/screen_cap.tool,sha256=v7l54PWWdgszdd-n_DFqI9nyMlBSeYeNIfQsdFYSZ_4,1389
65
+ npcsh-0.3.31.data/data/npcsh/npc_team/sibiji.npc,sha256=MJZHU9xXmvUbZvwpX1wWinvkrwYiKm1J63t37l0EYGE,202
66
+ npcsh-0.3.31.data/data/npcsh/npc_team/slean.npc,sha256=to3-d7qWMzhrYAeXalzNqVdt_3wROFGEfhprVXDttos,326
67
+ npcsh-0.3.31.data/data/npcsh/npc_team/sql_executor.tool,sha256=kEgxpb_9QUJpj8MEbzJY-isATG6Pi3KfVuffpwaoESM,808
68
+ npcsh-0.3.31.data/data/npcsh/npc_team/test_pipeline.py,sha256=GKIcqw0fXDHsUDfMvu7GTj5cfPnqs7aX5xxiKPs2xCc,5657
69
+ npcsh-0.3.31.data/data/npcsh/npc_team/turnic.npc,sha256=odTFzQTN01-xaWXvjoC698htaFi6mvrzfKMAob8Yqb0,335
70
+ npcsh-0.3.31.data/data/npcsh/npc_team/welxor.npc,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
71
+ npcsh-0.3.31.dist-info/licenses/LICENSE,sha256=j0YPvce7Ng9e32zYOu0EmXjXeJ0Nwawd0RA3uSGGH4E,1070
72
+ npcsh-0.3.31.dist-info/METADATA,sha256=Tas3A6_9dSVxgqBPiYZcTcdsFIWyCXmcEQsuXDQ6IPo,82638
73
+ npcsh-0.3.31.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
74
+ npcsh-0.3.31.dist-info/entry_points.txt,sha256=Y2rAM_m1er_Effxc0DXtGh36sC1FOUfefqGAt6vEte0,64
75
+ npcsh-0.3.31.dist-info/top_level.txt,sha256=kHSNgKMCkfjV95-DH0YSp1LLBi0HXdF3w57j7MQON3E,6
76
+ npcsh-0.3.31.dist-info/RECORD,,
File without changes