blue-assistant 4.273.1__tar.gz → 4.288.1__tar.gz

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 (81) hide show
  1. {blue_assistant-4.273.1/blue_assistant.egg-info → blue_assistant-4.288.1}/PKG-INFO +2 -2
  2. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/README.md +1 -1
  3. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/__init__.py +1 -1
  4. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/script/actions/web_crawl.py +4 -4
  5. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/web/__main__.py +2 -7
  6. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/web/crawl.py +47 -13
  7. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/web/fetch.py +25 -7
  8. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/web/functions.py +0 -15
  9. {blue_assistant-4.273.1 → blue_assistant-4.288.1/blue_assistant.egg-info}/PKG-INFO +2 -2
  10. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/LICENSE +0 -0
  11. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/MANIFEST.in +0 -0
  12. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/.abcli/abcli.sh +0 -0
  13. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/.abcli/actions.sh +0 -0
  14. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/.abcli/alias.sh +0 -0
  15. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/.abcli/blue_assistant.sh +0 -0
  16. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/.abcli/browse.sh +0 -0
  17. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/.abcli/hue/create_user.sh +0 -0
  18. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/.abcli/hue/list.sh +0 -0
  19. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/.abcli/hue/set.sh +0 -0
  20. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/.abcli/hue.sh +0 -0
  21. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/.abcli/script/list.sh +0 -0
  22. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/.abcli/script/run.sh +0 -0
  23. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/.abcli/script.sh +0 -0
  24. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/.abcli/tests/README.sh +0 -0
  25. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/.abcli/tests/help.sh +0 -0
  26. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/.abcli/tests/script_list.sh +0 -0
  27. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/.abcli/tests/script_run.sh +0 -0
  28. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/.abcli/tests/version.sh +0 -0
  29. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/.abcli/tests/web_crawl.sh +0 -0
  30. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/.abcli/tests/web_fetch.sh +0 -0
  31. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/.abcli/web/crawl.sh +0 -0
  32. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/.abcli/web/fetch.sh +0 -0
  33. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/.abcli/web.sh +0 -0
  34. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/README.py +0 -0
  35. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/__main__.py +0 -0
  36. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/config.env +0 -0
  37. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/env.py +0 -0
  38. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/functions.py +0 -0
  39. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/help/__init__.py +0 -0
  40. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/help/__main__.py +0 -0
  41. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/help/functions.py +0 -0
  42. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/help/hue.py +0 -0
  43. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/help/script.py +0 -0
  44. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/help/web.py +0 -0
  45. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/host.py +0 -0
  46. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/logger.py +0 -0
  47. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/sample.env +0 -0
  48. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/script/__init__.py +0 -0
  49. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/script/__main__.py +0 -0
  50. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/script/actions/__init__.py +0 -0
  51. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/script/actions/generate_image.py +0 -0
  52. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/script/actions/generate_text.py +0 -0
  53. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/script/actions/generic.py +0 -0
  54. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/script/load.py +0 -0
  55. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/script/repository/__init__.py +0 -0
  56. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/script/repository/base/__init__.py +0 -0
  57. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/script/repository/base/classes.py +0 -0
  58. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/script/repository/blue_amo/__init__.py +0 -0
  59. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/script/repository/blue_amo/actions/__init__.py +0 -0
  60. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/script/repository/blue_amo/actions/slicing_into_frames.py +0 -0
  61. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/script/repository/blue_amo/actions/stitching_the_frames.py +0 -0
  62. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/script/repository/blue_amo/classes.py +0 -0
  63. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/script/repository/generic/__init__.py +0 -0
  64. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/script/repository/generic/classes.py +0 -0
  65. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/script/repository/hue/__init__.py +0 -0
  66. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/script/repository/hue/__main__.py +0 -0
  67. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/script/repository/hue/api.py +0 -0
  68. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/script/repository/hue/classes.py +0 -0
  69. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/script/repository/hue/colors.py +0 -0
  70. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/script/repository/orbital_data_explorer/__init__.py +0 -0
  71. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/script/repository/orbital_data_explorer/classes.py +0 -0
  72. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/urls.py +0 -0
  73. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant/web/__init__.py +0 -0
  74. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant.egg-info/SOURCES.txt +0 -0
  75. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant.egg-info/dependency_links.txt +0 -0
  76. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant.egg-info/requires.txt +0 -0
  77. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/blue_assistant.egg-info/top_level.txt +0 -0
  78. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/pyproject.toml +0 -0
  79. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/requirements.txt +0 -0
  80. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/setup.cfg +0 -0
  81. {blue_assistant-4.273.1 → blue_assistant-4.288.1}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: blue_assistant
3
- Version: 4.273.1
3
+ Version: 4.288.1
4
4
  Summary: 🧠 An AI Assistant.
5
5
  Home-page: https://github.com/kamangir/blue-assistant
6
6
  Author: Arash Abadpour (Kamangir)
@@ -124,4 +124,4 @@ Also home to [`@web`](https://raw.githubusercontent.com/kamangir/blue-assistant/
124
124
 
125
125
  [![pylint](https://github.com/kamangir/blue-assistant/actions/workflows/pylint.yml/badge.svg)](https://github.com/kamangir/blue-assistant/actions/workflows/pylint.yml) [![pytest](https://github.com/kamangir/blue-assistant/actions/workflows/pytest.yml/badge.svg)](https://github.com/kamangir/blue-assistant/actions/workflows/pytest.yml) [![bashtest](https://github.com/kamangir/blue-assistant/actions/workflows/bashtest.yml/badge.svg)](https://github.com/kamangir/blue-assistant/actions/workflows/bashtest.yml) [![PyPI version](https://img.shields.io/pypi/v/blue-assistant.svg)](https://pypi.org/project/blue-assistant/) [![PyPI - Downloads](https://img.shields.io/pypi/dd/blue-assistant)](https://pypistats.org/packages/blue-assistant)
126
126
 
127
- built by 🌀 [`blue_options-4.236.1`](https://github.com/kamangir/awesome-bash-cli), based on 🧠 [`blue_assistant-4.273.1`](https://github.com/kamangir/blue-assistant).
127
+ built by 🌀 [`blue_options-4.240.1`](https://github.com/kamangir/awesome-bash-cli), based on 🧠 [`blue_assistant-4.288.1`](https://github.com/kamangir/blue-assistant).
@@ -79,4 +79,4 @@ Also home to [`@web`](./blue_assistant/web/)
79
79
 
80
80
  [![pylint](https://github.com/kamangir/blue-assistant/actions/workflows/pylint.yml/badge.svg)](https://github.com/kamangir/blue-assistant/actions/workflows/pylint.yml) [![pytest](https://github.com/kamangir/blue-assistant/actions/workflows/pytest.yml/badge.svg)](https://github.com/kamangir/blue-assistant/actions/workflows/pytest.yml) [![bashtest](https://github.com/kamangir/blue-assistant/actions/workflows/bashtest.yml/badge.svg)](https://github.com/kamangir/blue-assistant/actions/workflows/bashtest.yml) [![PyPI version](https://img.shields.io/pypi/v/blue-assistant.svg)](https://pypi.org/project/blue-assistant/) [![PyPI - Downloads](https://img.shields.io/pypi/dd/blue-assistant)](https://pypistats.org/packages/blue-assistant)
81
81
 
82
- built by 🌀 [`blue_options-4.236.1`](https://github.com/kamangir/awesome-bash-cli), based on 🧠 [`blue_assistant-4.273.1`](https://github.com/kamangir/blue-assistant).
82
+ built by 🌀 [`blue_options-4.240.1`](https://github.com/kamangir/awesome-bash-cli), based on 🧠 [`blue_assistant-4.288.1`](https://github.com/kamangir/blue-assistant).
@@ -4,7 +4,7 @@ ICON = "🧠"
4
4
 
5
5
  DESCRIPTION = f"{ICON} An AI Assistant."
6
6
 
7
- VERSION = "4.273.1"
7
+ VERSION = "4.288.1"
8
8
 
9
9
  REPO_NAME = "blue-assistant"
10
10
 
@@ -34,16 +34,16 @@ def web_crawl(
34
34
  logger.error(f"{node_name}: {seed_url_var_name}: seed_urls not found in vars.")
35
35
  return False
36
36
  seed_urls = script.vars[seed_url_var_name]
37
- log_list(logger, seed_urls, "seed url(s)")
37
+ log_list(logger, "using", seed_urls, "seed url(s)")
38
38
 
39
- visited_urls = crawl_list_of_urls(
39
+ crawl_cache = crawl_list_of_urls(
40
40
  seed_urls=seed_urls,
41
41
  object_name=script.object_name,
42
42
  max_iterations=script.nodes[node_name]["max_iterations"],
43
43
  use_cache=use_cache,
44
+ cache_prefix=node_name,
44
45
  )
45
46
 
46
- script.nodes[node_name]["visited_urls"] = visited_urls
47
- script.nodes[node_name]["output"] = "TBA"
47
+ script.nodes[node_name]["output"] = crawl_cache
48
48
 
49
49
  return True
@@ -50,6 +50,7 @@ args = parser.parse_args()
50
50
 
51
51
  success = False
52
52
  if args.task == "crawl":
53
+ success = True
53
54
  dict_of_urls = crawl_list_of_urls(
54
55
  seed_urls=args.seed_urls.split("+"),
55
56
  object_name=args.object_name,
@@ -58,13 +59,7 @@ if args.task == "crawl":
58
59
  )
59
60
 
60
61
  if args.verbose == 1:
61
- log_dict(logger, dict_of_urls, "url(s)")
62
-
63
- success = post_to_object(
64
- args.object_name,
65
- NAME.replace(".", "-"),
66
- dict_of_urls,
67
- )
62
+ log_dict(logger, "crawled", dict_of_urls, "url(s)")
68
63
  elif args.task == "fetch":
69
64
  summary = fetch_links_and_text(
70
65
  url=args.url,
@@ -1,6 +1,7 @@
1
- from typing import List, Dict, Set
1
+ from typing import List, Dict
2
2
 
3
3
  from blueness import module
4
+ from blue_options.logger import log_dict, log_list
4
5
  from blue_objects import file
5
6
  from blue_objects import objects
6
7
  from blue_objects.metadata import get_from_object, post_to_object
@@ -19,6 +20,7 @@ def crawl_list_of_urls(
19
20
  max_iterations: int = 10,
20
21
  use_cache: bool = False,
21
22
  verbose: bool = False,
23
+ cache_prefix: str = "",
22
24
  ) -> Dict[str, str]:
23
25
  logger.info(
24
26
  "{}.crawl_list_of_urls({}): {} -{}> {}".format(
@@ -30,24 +32,35 @@ def crawl_list_of_urls(
30
32
  )
31
33
  )
32
34
 
33
- crawl_cache: Dict[str, str] = (
34
- get_from_object(
35
+ crawl_cache: Dict[str, str] = {}
36
+ queue: List[str] = [url for url in seed_urls]
37
+
38
+ if use_cache:
39
+ crawl_cache = get_from_object(
35
40
  object_name,
36
41
  "crawl_cache",
37
42
  {},
38
43
  )
39
- if use_cache
40
- else {}
41
- )
44
+ log_dict(logger, "loaded cache:", crawl_cache, "url(s)")
42
45
 
43
- queue: Set[str] = set(seed_urls)
46
+ queue += get_from_object(
47
+ object_name,
48
+ "crawl_queue",
49
+ [],
50
+ )
51
+
52
+ log_list(logger, "queue:", queue, "url(s)")
44
53
 
45
54
  iteration: int = 0
46
55
  while queue:
47
- url = queue.pop()
56
+ url = queue[0]
57
+ queue = queue[1:]
58
+
48
59
  logger.info(
49
- "{} {} ...".format(
50
- "✅" if url in crawl_cache else "🔗",
60
+ "{} [#{:,}/{:,}]: {} ".format(
61
+ "✅ " if url in crawl_cache else "🔗 ",
62
+ iteration,
63
+ len(queue),
51
64
  url,
52
65
  )
53
66
  )
@@ -64,14 +77,26 @@ def crawl_list_of_urls(
64
77
  file.save_yaml(
65
78
  filename=objects.path_of(
66
79
  object_name=object_name,
67
- filename="crawl_summary_cache/{}.yaml".format(url_to_filename(url)),
80
+ filename="{}-crawl_cache/{}.yaml".format(
81
+ cache_prefix,
82
+ url_to_filename(url),
83
+ ),
68
84
  ),
69
85
  data=url_summary,
70
86
  )
71
87
 
72
88
  crawl_cache[url] = content_type
73
- if "links" in url_summary:
74
- queue.update(url_summary["links"] - crawl_cache.keys())
89
+
90
+ queue = (
91
+ queue
92
+ + url_summary.get("list_of_urls", [])
93
+ + [
94
+ url
95
+ for url in url_summary.get("list_of_ignored_urls", [])
96
+ if any(url.startswith(url_prefix) for url_prefix in seed_urls)
97
+ ]
98
+ )
99
+ queue = list({url for url in queue if url not in crawl_cache.keys()})
75
100
 
76
101
  iteration += 1
77
102
  if max_iterations != -1 and iteration >= max_iterations:
@@ -88,4 +113,13 @@ def crawl_list_of_urls(
88
113
  crawl_cache,
89
114
  )
90
115
 
116
+ post_to_object(
117
+ object_name,
118
+ "crawl_queue",
119
+ queue,
120
+ )
121
+
122
+ log_dict(logger, "crawled", crawl_cache, "url(s)")
123
+ log_list(logger, "queue:", queue, "url(s)")
124
+
91
125
  return crawl_cache
@@ -1,4 +1,4 @@
1
- from typing import Dict, Any
1
+ from typing import Dict, Any, List
2
2
  import requests
3
3
  from bs4 import BeautifulSoup, XMLParsedAsHTMLWarning
4
4
  from urllib.parse import urljoin
@@ -33,7 +33,8 @@ def fetch_links_and_text(
33
33
  content_type = response.headers.get("Content-Type", "")
34
34
  logger.info(f"content-type: {content_type}")
35
35
 
36
- links = set()
36
+ list_of_urls: List[str] = []
37
+ list_of_ignored_urls: List[str] = []
37
38
  text = ""
38
39
 
39
40
  if not any(
@@ -48,12 +49,19 @@ def fetch_links_and_text(
48
49
  for a_tag in soup.find_all("a", href=True):
49
50
  a_url = urljoin(url, a_tag["href"])
50
51
 
52
+ if "#" in a_url:
53
+ a_url = a_url.split("#", 1)[0]
54
+
51
55
  if a_url.startswith(url):
52
- logger.info(f"+= {a_url}")
53
- links.add(a_url)
56
+ if url not in list_of_urls:
57
+ logger.info(f"+= {a_url}")
58
+ list_of_urls += [a_url]
54
59
  continue
55
60
 
56
- logger.info(f"ignored: {a_url}")
61
+ if a_url not in list_of_ignored_urls:
62
+ list_of_ignored_urls += [a_url]
63
+ if verbose:
64
+ logger.info(f"ignored: {a_url}")
57
65
 
58
66
  text = soup.get_text(separator=" ", strip=True)
59
67
 
@@ -64,12 +72,22 @@ def fetch_links_and_text(
64
72
  text = re.sub(r"\s+", " ", text).strip()
65
73
 
66
74
  if verbose:
67
- log_list(logger, list(links), "link(s)")
75
+ log_list(logger, "fetched", list_of_urls, "url(s)")
76
+ log_list(logger, "ignored", list_of_ignored_urls, "url(s)")
68
77
  log_long_text(logger, text)
78
+ else:
79
+ logger.info(
80
+ "{} url(s) collected, {} url(s) ignored, text: {:,} char(s).".format(
81
+ len(list_of_urls),
82
+ len(list_of_ignored_urls),
83
+ len(text),
84
+ )
85
+ )
69
86
 
70
87
  return {
71
88
  "url": url,
72
89
  "content_type": content_type,
73
- "links": links,
90
+ "list_of_ignored_urls": list_of_ignored_urls,
91
+ "list_of_urls": list_of_urls,
74
92
  "text": text,
75
93
  }
@@ -1,19 +1,4 @@
1
- from typing import List, Dict, Set, Tuple
2
- import requests
3
- from bs4 import BeautifulSoup, XMLParsedAsHTMLWarning
4
- from urllib.parse import urljoin
5
1
  import re
6
- import warnings
7
-
8
- from blueness import module
9
- from blue_options.logger import log_long_text, log_list
10
-
11
- from blue_assistant import NAME
12
- from blue_assistant.logger import logger
13
-
14
- warnings.filterwarnings("ignore", category=XMLParsedAsHTMLWarning)
15
-
16
- NAME = module.name(__file__, NAME)
17
2
 
18
3
 
19
4
  def url_to_filename(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: blue_assistant
3
- Version: 4.273.1
3
+ Version: 4.288.1
4
4
  Summary: 🧠 An AI Assistant.
5
5
  Home-page: https://github.com/kamangir/blue-assistant
6
6
  Author: Arash Abadpour (Kamangir)
@@ -124,4 +124,4 @@ Also home to [`@web`](https://raw.githubusercontent.com/kamangir/blue-assistant/
124
124
 
125
125
  [![pylint](https://github.com/kamangir/blue-assistant/actions/workflows/pylint.yml/badge.svg)](https://github.com/kamangir/blue-assistant/actions/workflows/pylint.yml) [![pytest](https://github.com/kamangir/blue-assistant/actions/workflows/pytest.yml/badge.svg)](https://github.com/kamangir/blue-assistant/actions/workflows/pytest.yml) [![bashtest](https://github.com/kamangir/blue-assistant/actions/workflows/bashtest.yml/badge.svg)](https://github.com/kamangir/blue-assistant/actions/workflows/bashtest.yml) [![PyPI version](https://img.shields.io/pypi/v/blue-assistant.svg)](https://pypi.org/project/blue-assistant/) [![PyPI - Downloads](https://img.shields.io/pypi/dd/blue-assistant)](https://pypistats.org/packages/blue-assistant)
126
126
 
127
- built by 🌀 [`blue_options-4.236.1`](https://github.com/kamangir/awesome-bash-cli), based on 🧠 [`blue_assistant-4.273.1`](https://github.com/kamangir/blue-assistant).
127
+ built by 🌀 [`blue_options-4.240.1`](https://github.com/kamangir/awesome-bash-cli), based on 🧠 [`blue_assistant-4.288.1`](https://github.com/kamangir/blue-assistant).