feat: Embedded baseline MCP config and global tools
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"mcpServers": {
|
||||
"github": {
|
||||
"command": "docker",
|
||||
"args": [
|
||||
"run",
|
||||
"-i",
|
||||
"--rm",
|
||||
"-e",
|
||||
"GITHUB_PERSONAL_ACCESS_TOKEN",
|
||||
"ghcr.io/github/github-mcp-server"
|
||||
],
|
||||
"env": {
|
||||
"GITHUB_PERSONAL_ACCESS_TOKEN": "{{GITHUB_PERSONAL_ACCESS_TOKEN}}"
|
||||
}
|
||||
},
|
||||
"gitmcp": {
|
||||
"command": "npx",
|
||||
"args": ["mcp-remote", "https://gitmcp.io/docs"]
|
||||
},
|
||||
"docker": {
|
||||
"command": "uvx",
|
||||
"args": ["docker-mcp"]
|
||||
},
|
||||
"slack": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "slack-mcp-server@latest", "--transport", "stdio"],
|
||||
"env": {
|
||||
"SLACK_MCP_XOXC_TOKEN": "{{SLACK_MCP_XOXC_TOKEN}}",
|
||||
"SLACK_MCP_XOXD_TOKEN": "{{SLACK_MCP_XOXD_TOKEN}}",
|
||||
"SLACK_MCP_ADD_MESSAGE_TOOL": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
# demo_py.py
|
||||
# demo_sh.sh
|
||||
execute_command.sh
|
||||
# execute_py_code.py
|
||||
# execute_sql_code.sh
|
||||
# fetch_url_via_curl.sh
|
||||
# fetch_url_via_jina.sh
|
||||
fs_cat.sh
|
||||
fs_ls.sh
|
||||
# fs_mkdir.sh
|
||||
# fs_patch.sh
|
||||
# fs_write.sh
|
||||
get_current_time.sh
|
||||
# get_current_weather.py
|
||||
get_current_weather.sh
|
||||
query_jira_issues.sh
|
||||
# search_arxiv.sh
|
||||
# search_wikipedia.sh
|
||||
# search_wolframalpha.sh
|
||||
# send_mail.sh
|
||||
# send_twilio.sh
|
||||
# web_search_loki.sh
|
||||
# web_search_perplexity.sh
|
||||
# web_search_tavily.sh
|
||||
@@ -0,0 +1,38 @@
|
||||
import os
|
||||
from typing import List, Literal, Optional
|
||||
|
||||
def run(
|
||||
string: str,
|
||||
string_enum: Literal["foo", "bar"],
|
||||
boolean: bool,
|
||||
integer: int,
|
||||
number: float,
|
||||
array: List[str],
|
||||
string_optional: Optional[str] = None,
|
||||
array_optional: Optional[List[str]] = None,
|
||||
):
|
||||
"""Demonstrates how to create a tool using Python and how to use comments.
|
||||
Args:
|
||||
string: Define a required string property
|
||||
string_enum: Define a required string property with enum
|
||||
boolean: Define a required boolean property
|
||||
integer: Define a required integer property
|
||||
number: Define a required number property
|
||||
array: Define a required string array property
|
||||
string_optional: Define an optional string property
|
||||
array_optional: Define an optional string array property
|
||||
"""
|
||||
output = f"""string: {string}
|
||||
string_enum: {string_enum}
|
||||
string_optional: {string_optional}
|
||||
boolean: {boolean}
|
||||
integer: {integer}
|
||||
number: {number}
|
||||
array: {array}
|
||||
array_optional: {array_optional}"""
|
||||
|
||||
for key, value in os.environ.items():
|
||||
if key.startswith("LLM_"):
|
||||
output = f"{output}\n{key}: {value}"
|
||||
|
||||
return output
|
||||
Executable
+29
@@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
# @describe Demonstrate how to create a tool using Bash and how to use comment tags.
|
||||
# @option --string! Define a required string property
|
||||
# @option --string-enum![foo|bar] Define a required string property with enum
|
||||
# @option --string-optional Define a optional string property
|
||||
# @flag --boolean Define a boolean property
|
||||
# @option --integer! <INT> Define a required integer property
|
||||
# @option --number! <NUM> Define a required number property
|
||||
# @option --array+ <VALUE> Define a required string array property
|
||||
# @option --array-optional* Define a optional string array property
|
||||
|
||||
# @env LLM_OUTPUT=/dev/stdout The output path
|
||||
|
||||
# shellcheck disable=SC2154
|
||||
main() {
|
||||
cat <<EOF >> "$LLM_OUTPUT"
|
||||
string: ${argc_string}
|
||||
string_enum: ${argc_string_enum}
|
||||
string_optional: ${argc_string_optional}
|
||||
boolean: ${argc_boolean}
|
||||
integer: ${argc_integer}
|
||||
number: ${argc_number}
|
||||
array: ${argc_array[@]}
|
||||
array_optional: ${argc_array_optional[@]}
|
||||
$(printenv | grep '^LLM_')
|
||||
EOF
|
||||
}
|
||||
Executable
+204
@@ -0,0 +1,204 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
# @describe Execute the shell command.
|
||||
# @option --command! The command to execute.
|
||||
|
||||
# @env LLM_OUTPUT=/dev/stdout The output path
|
||||
|
||||
PROMPT_UTILS="${LLM_ROOT_DIR:-$(dirname "${BASH_SOURCE[0]}")/..}/utils/prompt-utils.sh"
|
||||
# shellcheck disable=SC1090
|
||||
source "$PROMPT_UTILS"
|
||||
|
||||
main() {
|
||||
guard_operation
|
||||
# shellcheck disable=SC2154
|
||||
eval "$argc_command" >> "$LLM_OUTPUT"
|
||||
}
|
||||
|
||||
# ARGC-BUILD {
|
||||
# This block was generated by argc (https://github.com/sigoden/argc).
|
||||
# Modifying it manually is not recommended
|
||||
|
||||
_argc_run() {
|
||||
if [[ "${1:-}" == "___internal___" ]]; then
|
||||
_argc_die "error: unsupported ___internal___ command"
|
||||
fi
|
||||
if [[ "${OS:-}" == "Windows_NT" ]] && [[ -n "${MSYSTEM:-}" ]]; then
|
||||
set -o igncr
|
||||
fi
|
||||
argc__args=("$(basename "$0" .sh)" "$@")
|
||||
argc__positionals=()
|
||||
_argc_index=1
|
||||
_argc_len="${#argc__args[@]}"
|
||||
_argc_tools=()
|
||||
_argc_parse
|
||||
if [ -n "${argc__fn:-}" ]; then
|
||||
$argc__fn "${argc__positionals[@]}"
|
||||
fi
|
||||
}
|
||||
|
||||
_argc_usage() {
|
||||
cat <<-'EOF'
|
||||
Execute the shell command.
|
||||
|
||||
USAGE: --command <COMMAND>
|
||||
|
||||
OPTIONS:
|
||||
--command <COMMAND> The command to execute.
|
||||
-h, --help Print help
|
||||
-V, --version Print version
|
||||
|
||||
ENVIRONMENTS:
|
||||
LLM_OUTPUT The output path [default: /dev/stdout]
|
||||
EOF
|
||||
exit
|
||||
}
|
||||
|
||||
_argc_version() {
|
||||
echo 0.0.0
|
||||
exit
|
||||
}
|
||||
|
||||
_argc_parse() {
|
||||
local _argc_key _argc_action
|
||||
local _argc_subcmds=""
|
||||
while [[ $_argc_index -lt $_argc_len ]]; do
|
||||
_argc_item="${argc__args[_argc_index]}"
|
||||
_argc_key="${_argc_item%%=*}"
|
||||
case "$_argc_key" in
|
||||
--help | -help | -h)
|
||||
_argc_usage
|
||||
;;
|
||||
--version | -version | -V)
|
||||
_argc_version
|
||||
;;
|
||||
--)
|
||||
_argc_dash="${#argc__positionals[@]}"
|
||||
argc__positionals+=("${argc__args[@]:$((_argc_index + 1))}")
|
||||
_argc_index=$_argc_len
|
||||
break
|
||||
;;
|
||||
--command)
|
||||
_argc_take_args "--command <COMMAND>" 1 1 "-" ""
|
||||
_argc_index=$((_argc_index + _argc_take_args_len + 1))
|
||||
if [[ -z "${argc_command:-}" ]]; then
|
||||
argc_command="${_argc_take_args_values[0]:-}"
|
||||
else
|
||||
_argc_die "error: the argument \`--command\` cannot be used multiple times"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
if _argc_maybe_flag_option "-" "$_argc_item"; then
|
||||
_argc_die "error: unexpected argument \`$_argc_key\` found"
|
||||
fi
|
||||
argc__positionals+=("$_argc_item")
|
||||
_argc_index=$((_argc_index + 1))
|
||||
;;
|
||||
esac
|
||||
done
|
||||
_argc_require_params "error: the following required arguments were not provided:" \
|
||||
'argc_command:--command <COMMAND>'
|
||||
if [[ -n "${_argc_action:-}" ]]; then
|
||||
$_argc_action
|
||||
else
|
||||
argc__fn=main
|
||||
if [[ "${argc__positionals[0]:-}" == "help" ]] && [[ "${#argc__positionals[@]}" -eq 1 ]]; then
|
||||
_argc_usage
|
||||
fi
|
||||
if [[ -z "${LLM_OUTPUT:-}" ]]; then
|
||||
export LLM_OUTPUT=/dev/stdout
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
_argc_take_args() {
|
||||
_argc_take_args_values=()
|
||||
_argc_take_args_len=0
|
||||
local param="$1" min="$2" max="$3" signs="$4" delimiter="$5"
|
||||
if [[ "$min" -eq 0 ]] && [[ "$max" -eq 0 ]]; then
|
||||
return
|
||||
fi
|
||||
local _argc_take_index=$((_argc_index + 1)) _argc_take_value
|
||||
if [[ "$_argc_item" == *=* ]]; then
|
||||
_argc_take_args_values=("${_argc_item##*=}")
|
||||
else
|
||||
while [[ $_argc_take_index -lt $_argc_len ]]; do
|
||||
_argc_take_value="${argc__args[_argc_take_index]}"
|
||||
if _argc_maybe_flag_option "$signs" "$_argc_take_value"; then
|
||||
if [[ "${#_argc_take_value}" -gt 1 ]]; then
|
||||
break
|
||||
fi
|
||||
fi
|
||||
_argc_take_args_values+=("$_argc_take_value")
|
||||
_argc_take_args_len=$((_argc_take_args_len + 1))
|
||||
if [[ "$_argc_take_args_len" -ge "$max" ]]; then
|
||||
break
|
||||
fi
|
||||
_argc_take_index=$((_argc_take_index + 1))
|
||||
done
|
||||
fi
|
||||
if [[ "${#_argc_take_args_values[@]}" -lt "$min" ]]; then
|
||||
_argc_die "error: incorrect number of values for \`$param\`"
|
||||
fi
|
||||
if [[ -n "$delimiter" ]] && [[ "${#_argc_take_args_values[@]}" -gt 0 ]]; then
|
||||
local item values arr=()
|
||||
for item in "${_argc_take_args_values[@]}"; do
|
||||
IFS="$delimiter" read -r -a values <<<"$item"
|
||||
arr+=("${values[@]}")
|
||||
done
|
||||
_argc_take_args_values=("${arr[@]}")
|
||||
fi
|
||||
}
|
||||
|
||||
_argc_require_params() {
|
||||
local message="$1" missed_envs="" item name render_name
|
||||
for item in "${@:2}"; do
|
||||
name="${item%%:*}"
|
||||
render_name="${item##*:}"
|
||||
if [[ -z "${!name:-}" ]]; then
|
||||
missed_envs="$missed_envs"$'\n'" $render_name"
|
||||
fi
|
||||
done
|
||||
if [[ -n "${missed_envs}" ]]; then
|
||||
_argc_die "$message$missed_envs"
|
||||
fi
|
||||
}
|
||||
|
||||
_argc_maybe_flag_option() {
|
||||
local signs="$1" arg="$2"
|
||||
if [[ -z "$signs" ]]; then
|
||||
return 1
|
||||
fi
|
||||
local cond=false
|
||||
if [[ "$signs" == *"+"* ]]; then
|
||||
if [[ "$arg" =~ ^\+[^+].* ]]; then
|
||||
cond=true
|
||||
fi
|
||||
elif [[ "$arg" == -* ]]; then
|
||||
if (( ${#arg} < 3 )) || [[ ! "$arg" =~ ^---.* ]]; then
|
||||
cond=true
|
||||
fi
|
||||
fi
|
||||
if [[ "$cond" == "false" ]]; then
|
||||
return 1
|
||||
fi
|
||||
local value="${arg%%=*}"
|
||||
if [[ "$value" =~ [[:space:]] ]]; then
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
_argc_die() {
|
||||
if [[ $# -eq 0 ]]; then
|
||||
cat
|
||||
else
|
||||
echo "$*" >&2
|
||||
fi
|
||||
exit 1
|
||||
}
|
||||
|
||||
_argc_run "$@"
|
||||
|
||||
# ARGC-BUILD }
|
||||
@@ -0,0 +1,33 @@
|
||||
import ast
|
||||
import io
|
||||
from contextlib import redirect_stdout
|
||||
|
||||
|
||||
def run(code: str):
|
||||
"""Execute the python code.
|
||||
Args:
|
||||
code: Python code to execute, such as `print("hello world")`
|
||||
"""
|
||||
output = io.StringIO()
|
||||
with redirect_stdout(output):
|
||||
value = exec_with_return(code, {}, {})
|
||||
|
||||
if value is not None:
|
||||
output.write(str(value))
|
||||
|
||||
return output.getvalue()
|
||||
|
||||
|
||||
def exec_with_return(code: str, globals: dict, locals: dict):
|
||||
a = ast.parse(code)
|
||||
last_expression = None
|
||||
if a.body:
|
||||
if isinstance(a_last := a.body[-1], ast.Expr):
|
||||
last_expression = ast.unparse(a.body.pop())
|
||||
elif isinstance(a_last, ast.Assign):
|
||||
last_expression = ast.unparse(a_last.targets[0])
|
||||
elif isinstance(a_last, (ast.AnnAssign, ast.AugAssign)):
|
||||
last_expression = ast.unparse(a_last.target)
|
||||
exec(ast.unparse(a), globals, locals)
|
||||
if last_expression:
|
||||
return eval(last_expression, globals, locals)
|
||||
Executable
+22
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
# @describe Execute sql code.
|
||||
# @option --code! The code to execute.
|
||||
|
||||
# @meta require-tools usql
|
||||
|
||||
# @env USQL_DSN! The database connection url. e.g. pgsql://user:pass@host:port
|
||||
# @env LLM_OUTPUT=/dev/stdout The output path
|
||||
|
||||
PROMPT_UTILS="${LLM_ROOT_DIR:-$(dirname "${BASH_SOURCE[0]}")/..}/utils/prompt-utils.sh"
|
||||
# shellcheck disable=SC1090
|
||||
source "$PROMPT_UTILS"
|
||||
|
||||
# shellcheck disable=SC2154
|
||||
main() {
|
||||
if ! grep -qi '^select' <<<"$argc_code"; then
|
||||
guard_operation ""
|
||||
fi
|
||||
usql -c "$argc_code" "$USQL_DSN" >> "$LLM_OUTPUT"
|
||||
}
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
# @describe Extract the content from a given URL.
|
||||
# @option --url! The URL to scrape.
|
||||
|
||||
# @meta require-tools pandoc
|
||||
|
||||
# @env LLM_OUTPUT=/dev/stdout The output path
|
||||
|
||||
# shellcheck disable=SC2154
|
||||
main() {
|
||||
# span and div tags are dropped from the HTML https://pandoc.org/MANUAL.html#raw-htmltex and sed removes any inline SVG images in image tags from the Markdown content.
|
||||
curl -fsSL "$argc_url" | \
|
||||
pandoc -f html-native_divs-native_spans -t gfm-raw_html --wrap=none | \
|
||||
sed -E 's/!\[[^]]*\]\([^)]*\)//g' \
|
||||
>> "$LLM_OUTPUT"
|
||||
}
|
||||
Executable
+17
@@ -0,0 +1,17 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
# @describe Extract the content from a given URL.
|
||||
# @option --url! The URL to scrape.
|
||||
|
||||
# @env JINA_API_KEY Your Jina API key
|
||||
# @env LLM_OUTPUT=/dev/stdout The output path
|
||||
|
||||
# shellcheck disable=SC2154
|
||||
main() {
|
||||
curl_args=()
|
||||
if [[ -n "$JINA_API_KEY" ]]; then
|
||||
curl_args+=("-H" "Authorization: Bearer $JINA_API_KEY")
|
||||
fi
|
||||
curl -fsSL "${curl_args[@]}" "https://r.jina.ai/$argc_url" >> "$LLM_OUTPUT"
|
||||
}
|
||||
Executable
+202
@@ -0,0 +1,202 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
# @describe Read the contents of a file at the specified path.
|
||||
# Use this when you need to examine the contents of an existing file.
|
||||
|
||||
# @option --path! The path of the file to read
|
||||
|
||||
# @env LLM_OUTPUT=/dev/stdout The output path
|
||||
|
||||
main() {
|
||||
# shellcheck disable=SC2154
|
||||
cat "$argc_path" >> "$LLM_OUTPUT"
|
||||
}
|
||||
|
||||
# ARGC-BUILD {
|
||||
# This block was generated by argc (https://github.com/sigoden/argc).
|
||||
# Modifying it manually is not recommended
|
||||
|
||||
_argc_run() {
|
||||
if [[ "${1:-}" == "___internal___" ]]; then
|
||||
_argc_die "error: unsupported ___internal___ command"
|
||||
fi
|
||||
if [[ "${OS:-}" == "Windows_NT" ]] && [[ -n "${MSYSTEM:-}" ]]; then
|
||||
set -o igncr
|
||||
fi
|
||||
argc__args=("$(basename "$0" .sh)" "$@")
|
||||
argc__positionals=()
|
||||
_argc_index=1
|
||||
_argc_len="${#argc__args[@]}"
|
||||
_argc_tools=()
|
||||
_argc_parse
|
||||
if [ -n "${argc__fn:-}" ]; then
|
||||
$argc__fn "${argc__positionals[@]}"
|
||||
fi
|
||||
}
|
||||
|
||||
_argc_usage() {
|
||||
cat <<-'EOF'
|
||||
Read the contents of a file at the specified path.
|
||||
Use this when you need to examine the contents of an existing file.
|
||||
|
||||
USAGE: --path <PATH>
|
||||
|
||||
OPTIONS:
|
||||
--path <PATH> The path of the file to read
|
||||
-h, --help Print help
|
||||
-V, --version Print version
|
||||
|
||||
ENVIRONMENTS:
|
||||
LLM_OUTPUT The output path [default: /dev/stdout]
|
||||
EOF
|
||||
exit
|
||||
}
|
||||
|
||||
_argc_version() {
|
||||
echo 0.0.0
|
||||
exit
|
||||
}
|
||||
|
||||
_argc_parse() {
|
||||
local _argc_key _argc_action
|
||||
local _argc_subcmds=""
|
||||
while [[ $_argc_index -lt $_argc_len ]]; do
|
||||
_argc_item="${argc__args[_argc_index]}"
|
||||
_argc_key="${_argc_item%%=*}"
|
||||
case "$_argc_key" in
|
||||
--help | -help | -h)
|
||||
_argc_usage
|
||||
;;
|
||||
--version | -version | -V)
|
||||
_argc_version
|
||||
;;
|
||||
--)
|
||||
_argc_dash="${#argc__positionals[@]}"
|
||||
argc__positionals+=("${argc__args[@]:$((_argc_index + 1))}")
|
||||
_argc_index=$_argc_len
|
||||
break
|
||||
;;
|
||||
--path)
|
||||
_argc_take_args "--path <PATH>" 1 1 "-" ""
|
||||
_argc_index=$((_argc_index + _argc_take_args_len + 1))
|
||||
if [[ -z "${argc_path:-}" ]]; then
|
||||
argc_path="${_argc_take_args_values[0]:-}"
|
||||
else
|
||||
_argc_die "error: the argument \`--path\` cannot be used multiple times"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
if _argc_maybe_flag_option "-" "$_argc_item"; then
|
||||
_argc_die "error: unexpected argument \`$_argc_key\` found"
|
||||
fi
|
||||
argc__positionals+=("$_argc_item")
|
||||
_argc_index=$((_argc_index + 1))
|
||||
;;
|
||||
esac
|
||||
done
|
||||
_argc_require_params "error: the following required arguments were not provided:" \
|
||||
'argc_path:--path <PATH>'
|
||||
if [[ -n "${_argc_action:-}" ]]; then
|
||||
$_argc_action
|
||||
else
|
||||
argc__fn=main
|
||||
if [[ "${argc__positionals[0]:-}" == "help" ]] && [[ "${#argc__positionals[@]}" -eq 1 ]]; then
|
||||
_argc_usage
|
||||
fi
|
||||
if [[ -z "${LLM_OUTPUT:-}" ]]; then
|
||||
export LLM_OUTPUT=/dev/stdout
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
_argc_take_args() {
|
||||
_argc_take_args_values=()
|
||||
_argc_take_args_len=0
|
||||
local param="$1" min="$2" max="$3" signs="$4" delimiter="$5"
|
||||
if [[ "$min" -eq 0 ]] && [[ "$max" -eq 0 ]]; then
|
||||
return
|
||||
fi
|
||||
local _argc_take_index=$((_argc_index + 1)) _argc_take_value
|
||||
if [[ "$_argc_item" == *=* ]]; then
|
||||
_argc_take_args_values=("${_argc_item##*=}")
|
||||
else
|
||||
while [[ $_argc_take_index -lt $_argc_len ]]; do
|
||||
_argc_take_value="${argc__args[_argc_take_index]}"
|
||||
if _argc_maybe_flag_option "$signs" "$_argc_take_value"; then
|
||||
if [[ "${#_argc_take_value}" -gt 1 ]]; then
|
||||
break
|
||||
fi
|
||||
fi
|
||||
_argc_take_args_values+=("$_argc_take_value")
|
||||
_argc_take_args_len=$((_argc_take_args_len + 1))
|
||||
if [[ "$_argc_take_args_len" -ge "$max" ]]; then
|
||||
break
|
||||
fi
|
||||
_argc_take_index=$((_argc_take_index + 1))
|
||||
done
|
||||
fi
|
||||
if [[ "${#_argc_take_args_values[@]}" -lt "$min" ]]; then
|
||||
_argc_die "error: incorrect number of values for \`$param\`"
|
||||
fi
|
||||
if [[ -n "$delimiter" ]] && [[ "${#_argc_take_args_values[@]}" -gt 0 ]]; then
|
||||
local item values arr=()
|
||||
for item in "${_argc_take_args_values[@]}"; do
|
||||
IFS="$delimiter" read -r -a values <<<"$item"
|
||||
arr+=("${values[@]}")
|
||||
done
|
||||
_argc_take_args_values=("${arr[@]}")
|
||||
fi
|
||||
}
|
||||
|
||||
_argc_require_params() {
|
||||
local message="$1" missed_envs="" item name render_name
|
||||
for item in "${@:2}"; do
|
||||
name="${item%%:*}"
|
||||
render_name="${item##*:}"
|
||||
if [[ -z "${!name:-}" ]]; then
|
||||
missed_envs="$missed_envs"$'\n'" $render_name"
|
||||
fi
|
||||
done
|
||||
if [[ -n "${missed_envs}" ]]; then
|
||||
_argc_die "$message$missed_envs"
|
||||
fi
|
||||
}
|
||||
|
||||
_argc_maybe_flag_option() {
|
||||
local signs="$1" arg="$2"
|
||||
if [[ -z "$signs" ]]; then
|
||||
return 1
|
||||
fi
|
||||
local cond=false
|
||||
if [[ "$signs" == *"+"* ]]; then
|
||||
if [[ "$arg" =~ ^\+[^+].* ]]; then
|
||||
cond=true
|
||||
fi
|
||||
elif [[ "$arg" == -* ]]; then
|
||||
if (( ${#arg} < 3 )) || [[ ! "$arg" =~ ^---.* ]]; then
|
||||
cond=true
|
||||
fi
|
||||
fi
|
||||
if [[ "$cond" == "false" ]]; then
|
||||
return 1
|
||||
fi
|
||||
local value="${arg%%=*}"
|
||||
if [[ "$value" =~ [[:space:]] ]]; then
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
_argc_die() {
|
||||
if [[ $# -eq 0 ]]; then
|
||||
cat
|
||||
else
|
||||
echo "$*" >&2
|
||||
fi
|
||||
exit 1
|
||||
}
|
||||
|
||||
_argc_run "$@"
|
||||
|
||||
# ARGC-BUILD }
|
||||
Executable
+200
@@ -0,0 +1,200 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
# @describe List all files and directories at the specified path.
|
||||
|
||||
# @option --path! The path of the directory to list
|
||||
|
||||
# @env LLM_OUTPUT=/dev/stdout The output path
|
||||
|
||||
main() {
|
||||
# shellcheck disable=SC2154
|
||||
ls -1 "$argc_path" >> "$LLM_OUTPUT"
|
||||
}
|
||||
|
||||
# ARGC-BUILD {
|
||||
# This block was generated by argc (https://github.com/sigoden/argc).
|
||||
# Modifying it manually is not recommended
|
||||
|
||||
_argc_run() {
|
||||
if [[ "${1:-}" == "___internal___" ]]; then
|
||||
_argc_die "error: unsupported ___internal___ command"
|
||||
fi
|
||||
if [[ "${OS:-}" == "Windows_NT" ]] && [[ -n "${MSYSTEM:-}" ]]; then
|
||||
set -o igncr
|
||||
fi
|
||||
argc__args=("$(basename "$0" .sh)" "$@")
|
||||
argc__positionals=()
|
||||
_argc_index=1
|
||||
_argc_len="${#argc__args[@]}"
|
||||
_argc_tools=()
|
||||
_argc_parse
|
||||
if [ -n "${argc__fn:-}" ]; then
|
||||
$argc__fn "${argc__positionals[@]}"
|
||||
fi
|
||||
}
|
||||
|
||||
_argc_usage() {
|
||||
cat <<-'EOF'
|
||||
List all files and directories at the specified path.
|
||||
|
||||
USAGE: --path <PATH>
|
||||
|
||||
OPTIONS:
|
||||
--path <PATH> The path of the directory to list
|
||||
-h, --help Print help
|
||||
-V, --version Print version
|
||||
|
||||
ENVIRONMENTS:
|
||||
LLM_OUTPUT The output path [default: /dev/stdout]
|
||||
EOF
|
||||
exit
|
||||
}
|
||||
|
||||
_argc_version() {
|
||||
echo 0.0.0
|
||||
exit
|
||||
}
|
||||
|
||||
_argc_parse() {
|
||||
local _argc_key _argc_action
|
||||
local _argc_subcmds=""
|
||||
while [[ $_argc_index -lt $_argc_len ]]; do
|
||||
_argc_item="${argc__args[_argc_index]}"
|
||||
_argc_key="${_argc_item%%=*}"
|
||||
case "$_argc_key" in
|
||||
--help | -help | -h)
|
||||
_argc_usage
|
||||
;;
|
||||
--version | -version | -V)
|
||||
_argc_version
|
||||
;;
|
||||
--)
|
||||
_argc_dash="${#argc__positionals[@]}"
|
||||
argc__positionals+=("${argc__args[@]:$((_argc_index + 1))}")
|
||||
_argc_index=$_argc_len
|
||||
break
|
||||
;;
|
||||
--path)
|
||||
_argc_take_args "--path <PATH>" 1 1 "-" ""
|
||||
_argc_index=$((_argc_index + _argc_take_args_len + 1))
|
||||
if [[ -z "${argc_path:-}" ]]; then
|
||||
argc_path="${_argc_take_args_values[0]:-}"
|
||||
else
|
||||
_argc_die "error: the argument \`--path\` cannot be used multiple times"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
if _argc_maybe_flag_option "-" "$_argc_item"; then
|
||||
_argc_die "error: unexpected argument \`$_argc_key\` found"
|
||||
fi
|
||||
argc__positionals+=("$_argc_item")
|
||||
_argc_index=$((_argc_index + 1))
|
||||
;;
|
||||
esac
|
||||
done
|
||||
_argc_require_params "error: the following required arguments were not provided:" \
|
||||
'argc_path:--path <PATH>'
|
||||
if [[ -n "${_argc_action:-}" ]]; then
|
||||
$_argc_action
|
||||
else
|
||||
argc__fn=main
|
||||
if [[ "${argc__positionals[0]:-}" == "help" ]] && [[ "${#argc__positionals[@]}" -eq 1 ]]; then
|
||||
_argc_usage
|
||||
fi
|
||||
if [[ -z "${LLM_OUTPUT:-}" ]]; then
|
||||
export LLM_OUTPUT=/dev/stdout
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
_argc_take_args() {
|
||||
_argc_take_args_values=()
|
||||
_argc_take_args_len=0
|
||||
local param="$1" min="$2" max="$3" signs="$4" delimiter="$5"
|
||||
if [[ "$min" -eq 0 ]] && [[ "$max" -eq 0 ]]; then
|
||||
return
|
||||
fi
|
||||
local _argc_take_index=$((_argc_index + 1)) _argc_take_value
|
||||
if [[ "$_argc_item" == *=* ]]; then
|
||||
_argc_take_args_values=("${_argc_item##*=}")
|
||||
else
|
||||
while [[ $_argc_take_index -lt $_argc_len ]]; do
|
||||
_argc_take_value="${argc__args[_argc_take_index]}"
|
||||
if _argc_maybe_flag_option "$signs" "$_argc_take_value"; then
|
||||
if [[ "${#_argc_take_value}" -gt 1 ]]; then
|
||||
break
|
||||
fi
|
||||
fi
|
||||
_argc_take_args_values+=("$_argc_take_value")
|
||||
_argc_take_args_len=$((_argc_take_args_len + 1))
|
||||
if [[ "$_argc_take_args_len" -ge "$max" ]]; then
|
||||
break
|
||||
fi
|
||||
_argc_take_index=$((_argc_take_index + 1))
|
||||
done
|
||||
fi
|
||||
if [[ "${#_argc_take_args_values[@]}" -lt "$min" ]]; then
|
||||
_argc_die "error: incorrect number of values for \`$param\`"
|
||||
fi
|
||||
if [[ -n "$delimiter" ]] && [[ "${#_argc_take_args_values[@]}" -gt 0 ]]; then
|
||||
local item values arr=()
|
||||
for item in "${_argc_take_args_values[@]}"; do
|
||||
IFS="$delimiter" read -r -a values <<<"$item"
|
||||
arr+=("${values[@]}")
|
||||
done
|
||||
_argc_take_args_values=("${arr[@]}")
|
||||
fi
|
||||
}
|
||||
|
||||
_argc_require_params() {
|
||||
local message="$1" missed_envs="" item name render_name
|
||||
for item in "${@:2}"; do
|
||||
name="${item%%:*}"
|
||||
render_name="${item##*:}"
|
||||
if [[ -z "${!name:-}" ]]; then
|
||||
missed_envs="$missed_envs"$'\n'" $render_name"
|
||||
fi
|
||||
done
|
||||
if [[ -n "${missed_envs}" ]]; then
|
||||
_argc_die "$message$missed_envs"
|
||||
fi
|
||||
}
|
||||
|
||||
_argc_maybe_flag_option() {
|
||||
local signs="$1" arg="$2"
|
||||
if [[ -z "$signs" ]]; then
|
||||
return 1
|
||||
fi
|
||||
local cond=false
|
||||
if [[ "$signs" == *"+"* ]]; then
|
||||
if [[ "$arg" =~ ^\+[^+].* ]]; then
|
||||
cond=true
|
||||
fi
|
||||
elif [[ "$arg" == -* ]]; then
|
||||
if (( ${#arg} < 3 )) || [[ ! "$arg" =~ ^---.* ]]; then
|
||||
cond=true
|
||||
fi
|
||||
fi
|
||||
if [[ "$cond" == "false" ]]; then
|
||||
return 1
|
||||
fi
|
||||
local value="${arg%%=*}"
|
||||
if [[ "$value" =~ [[:space:]] ]]; then
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
_argc_die() {
|
||||
if [[ $# -eq 0 ]]; then
|
||||
cat
|
||||
else
|
||||
echo "$*" >&2
|
||||
fi
|
||||
exit 1
|
||||
}
|
||||
|
||||
_argc_run "$@"
|
||||
|
||||
# ARGC-BUILD }
|
||||
Executable
+201
@@ -0,0 +1,201 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
# @describe Create a new directory at the specified path.
|
||||
|
||||
# @option --path! The path of the directory to create
|
||||
|
||||
# @env LLM_OUTPUT=/dev/stdout The output path
|
||||
|
||||
main() {
|
||||
# shellcheck disable=SC2154
|
||||
mkdir -p "$argc_path"
|
||||
echo "Directory created: $argc_path" >> "$LLM_OUTPUT"
|
||||
}
|
||||
|
||||
# ARGC-BUILD {
|
||||
# This block was generated by argc (https://github.com/sigoden/argc).
|
||||
# Modifying it manually is not recommended
|
||||
|
||||
_argc_run() {
|
||||
if [[ "${1:-}" == "___internal___" ]]; then
|
||||
_argc_die "error: unsupported ___internal___ command"
|
||||
fi
|
||||
if [[ "${OS:-}" == "Windows_NT" ]] && [[ -n "${MSYSTEM:-}" ]]; then
|
||||
set -o igncr
|
||||
fi
|
||||
argc__args=("$(basename "$0" .sh)" "$@")
|
||||
argc__positionals=()
|
||||
_argc_index=1
|
||||
_argc_len="${#argc__args[@]}"
|
||||
_argc_tools=()
|
||||
_argc_parse
|
||||
if [ -n "${argc__fn:-}" ]; then
|
||||
$argc__fn "${argc__positionals[@]}"
|
||||
fi
|
||||
}
|
||||
|
||||
_argc_usage() {
|
||||
cat <<-'EOF'
|
||||
Create a new directory at the specified path.
|
||||
|
||||
USAGE: --path <PATH>
|
||||
|
||||
OPTIONS:
|
||||
--path <PATH> The path of the directory to create
|
||||
-h, --help Print help
|
||||
-V, --version Print version
|
||||
|
||||
ENVIRONMENTS:
|
||||
LLM_OUTPUT The output path [default: /dev/stdout]
|
||||
EOF
|
||||
exit
|
||||
}
|
||||
|
||||
_argc_version() {
|
||||
echo 0.0.0
|
||||
exit
|
||||
}
|
||||
|
||||
_argc_parse() {
|
||||
local _argc_key _argc_action
|
||||
local _argc_subcmds=""
|
||||
while [[ $_argc_index -lt $_argc_len ]]; do
|
||||
_argc_item="${argc__args[_argc_index]}"
|
||||
_argc_key="${_argc_item%%=*}"
|
||||
case "$_argc_key" in
|
||||
--help | -help | -h)
|
||||
_argc_usage
|
||||
;;
|
||||
--version | -version | -V)
|
||||
_argc_version
|
||||
;;
|
||||
--)
|
||||
_argc_dash="${#argc__positionals[@]}"
|
||||
argc__positionals+=("${argc__args[@]:$((_argc_index + 1))}")
|
||||
_argc_index=$_argc_len
|
||||
break
|
||||
;;
|
||||
--path)
|
||||
_argc_take_args "--path <PATH>" 1 1 "-" ""
|
||||
_argc_index=$((_argc_index + _argc_take_args_len + 1))
|
||||
if [[ -z "${argc_path:-}" ]]; then
|
||||
argc_path="${_argc_take_args_values[0]:-}"
|
||||
else
|
||||
_argc_die "error: the argument \`--path\` cannot be used multiple times"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
if _argc_maybe_flag_option "-" "$_argc_item"; then
|
||||
_argc_die "error: unexpected argument \`$_argc_key\` found"
|
||||
fi
|
||||
argc__positionals+=("$_argc_item")
|
||||
_argc_index=$((_argc_index + 1))
|
||||
;;
|
||||
esac
|
||||
done
|
||||
_argc_require_params "error: the following required arguments were not provided:" \
|
||||
'argc_path:--path <PATH>'
|
||||
if [[ -n "${_argc_action:-}" ]]; then
|
||||
$_argc_action
|
||||
else
|
||||
argc__fn=main
|
||||
if [[ "${argc__positionals[0]:-}" == "help" ]] && [[ "${#argc__positionals[@]}" -eq 1 ]]; then
|
||||
_argc_usage
|
||||
fi
|
||||
if [[ -z "${LLM_OUTPUT:-}" ]]; then
|
||||
export LLM_OUTPUT=/dev/stdout
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
_argc_take_args() {
|
||||
_argc_take_args_values=()
|
||||
_argc_take_args_len=0
|
||||
local param="$1" min="$2" max="$3" signs="$4" delimiter="$5"
|
||||
if [[ "$min" -eq 0 ]] && [[ "$max" -eq 0 ]]; then
|
||||
return
|
||||
fi
|
||||
local _argc_take_index=$((_argc_index + 1)) _argc_take_value
|
||||
if [[ "$_argc_item" == *=* ]]; then
|
||||
_argc_take_args_values=("${_argc_item##*=}")
|
||||
else
|
||||
while [[ $_argc_take_index -lt $_argc_len ]]; do
|
||||
_argc_take_value="${argc__args[_argc_take_index]}"
|
||||
if _argc_maybe_flag_option "$signs" "$_argc_take_value"; then
|
||||
if [[ "${#_argc_take_value}" -gt 1 ]]; then
|
||||
break
|
||||
fi
|
||||
fi
|
||||
_argc_take_args_values+=("$_argc_take_value")
|
||||
_argc_take_args_len=$((_argc_take_args_len + 1))
|
||||
if [[ "$_argc_take_args_len" -ge "$max" ]]; then
|
||||
break
|
||||
fi
|
||||
_argc_take_index=$((_argc_take_index + 1))
|
||||
done
|
||||
fi
|
||||
if [[ "${#_argc_take_args_values[@]}" -lt "$min" ]]; then
|
||||
_argc_die "error: incorrect number of values for \`$param\`"
|
||||
fi
|
||||
if [[ -n "$delimiter" ]] && [[ "${#_argc_take_args_values[@]}" -gt 0 ]]; then
|
||||
local item values arr=()
|
||||
for item in "${_argc_take_args_values[@]}"; do
|
||||
IFS="$delimiter" read -r -a values <<<"$item"
|
||||
arr+=("${values[@]}")
|
||||
done
|
||||
_argc_take_args_values=("${arr[@]}")
|
||||
fi
|
||||
}
|
||||
|
||||
_argc_require_params() {
|
||||
local message="$1" missed_envs="" item name render_name
|
||||
for item in "${@:2}"; do
|
||||
name="${item%%:*}"
|
||||
render_name="${item##*:}"
|
||||
if [[ -z "${!name:-}" ]]; then
|
||||
missed_envs="$missed_envs"$'\n'" $render_name"
|
||||
fi
|
||||
done
|
||||
if [[ -n "${missed_envs}" ]]; then
|
||||
_argc_die "$message$missed_envs"
|
||||
fi
|
||||
}
|
||||
|
||||
_argc_maybe_flag_option() {
|
||||
local signs="$1" arg="$2"
|
||||
if [[ -z "$signs" ]]; then
|
||||
return 1
|
||||
fi
|
||||
local cond=false
|
||||
if [[ "$signs" == *"+"* ]]; then
|
||||
if [[ "$arg" =~ ^\+[^+].* ]]; then
|
||||
cond=true
|
||||
fi
|
||||
elif [[ "$arg" == -* ]]; then
|
||||
if (( ${#arg} < 3 )) || [[ ! "$arg" =~ ^---.* ]]; then
|
||||
cond=true
|
||||
fi
|
||||
fi
|
||||
if [[ "$cond" == "false" ]]; then
|
||||
return 1
|
||||
fi
|
||||
local value="${arg%%=*}"
|
||||
if [[ "$value" =~ [[:space:]] ]]; then
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
_argc_die() {
|
||||
if [[ $# -eq 0 ]]; then
|
||||
cat
|
||||
else
|
||||
echo "$*" >&2
|
||||
fi
|
||||
exit 1
|
||||
}
|
||||
|
||||
_argc_run "$@"
|
||||
|
||||
# ARGC-BUILD }
|
||||
Executable
+229
@@ -0,0 +1,229 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
# @describe Apply a patch to a file at the specified path.
|
||||
# This can be used to edit the file without having to rewrite the whole file.
|
||||
|
||||
# @option --path! The path of the file to apply the patch to
|
||||
# @option --contents! The patch to apply to the file
|
||||
|
||||
# @env LLM_OUTPUT=/dev/stdout The output path
|
||||
|
||||
PROMPT_UTILS="${LLM_ROOT_DIR:-$(dirname "${BASH_SOURCE[0]}")/..}/utils/prompt-utils.sh"
|
||||
# shellcheck disable=SC1090
|
||||
source "$PROMPT_UTILS"
|
||||
|
||||
# shellcheck disable=SC2154
|
||||
main() {
|
||||
if [[ ! -f "$argc_path" ]]; then
|
||||
error "Unable to find the specified file: $argc_path"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
new_contents="$(patch_file "$argc_path" <(printf "%s" "$argc_contents"))"
|
||||
printf "%s" "$new_contents" | git diff --no-index "$argc_path" - || true
|
||||
|
||||
guard_operation "Apply changes?"
|
||||
|
||||
printf "%s" "$new_contents" > "$argc_path"
|
||||
|
||||
info "Applied the patch to: $argc_path" >> "$LLM_OUTPUT"
|
||||
}
|
||||
|
||||
# ARGC-BUILD {
|
||||
# This block was generated by argc (https://github.com/sigoden/argc).
|
||||
# Modifying it manually is not recommended
|
||||
|
||||
_argc_run() {
|
||||
if [[ "${1:-}" == "___internal___" ]]; then
|
||||
_argc_die "error: unsupported ___internal___ command"
|
||||
fi
|
||||
if [[ "${OS:-}" == "Windows_NT" ]] && [[ -n "${MSYSTEM:-}" ]]; then
|
||||
set -o igncr
|
||||
fi
|
||||
argc__args=("$(basename "$0" .sh)" "$@")
|
||||
argc__positionals=()
|
||||
_argc_index=1
|
||||
_argc_len="${#argc__args[@]}"
|
||||
_argc_tools=()
|
||||
_argc_parse
|
||||
if [ -n "${argc__fn:-}" ]; then
|
||||
$argc__fn "${argc__positionals[@]}"
|
||||
fi
|
||||
}
|
||||
|
||||
_argc_usage() {
|
||||
cat <<-'EOF'
|
||||
Apply a patch to a file at the specified path.
|
||||
This can be used to edit the file without having to rewrite the whole file.
|
||||
|
||||
USAGE: --path <PATH> --contents <CONTENTS>
|
||||
|
||||
OPTIONS:
|
||||
--path <PATH> The path of the file to apply the patch to
|
||||
--contents <CONTENTS> The patch to apply to the file
|
||||
-h, --help Print help
|
||||
-V, --version Print version
|
||||
|
||||
ENVIRONMENTS:
|
||||
LLM_OUTPUT The output path [default: /dev/stdout]
|
||||
EOF
|
||||
exit
|
||||
}
|
||||
|
||||
_argc_version() {
|
||||
echo 0.0.0
|
||||
exit
|
||||
}
|
||||
|
||||
_argc_parse() {
|
||||
local _argc_key _argc_action
|
||||
local _argc_subcmds=""
|
||||
while [[ $_argc_index -lt $_argc_len ]]; do
|
||||
_argc_item="${argc__args[_argc_index]}"
|
||||
_argc_key="${_argc_item%%=*}"
|
||||
case "$_argc_key" in
|
||||
--help | -help | -h)
|
||||
_argc_usage
|
||||
;;
|
||||
--version | -version | -V)
|
||||
_argc_version
|
||||
;;
|
||||
--)
|
||||
_argc_dash="${#argc__positionals[@]}"
|
||||
argc__positionals+=("${argc__args[@]:$((_argc_index + 1))}")
|
||||
_argc_index=$_argc_len
|
||||
break
|
||||
;;
|
||||
--path)
|
||||
_argc_take_args "--path <PATH>" 1 1 "-" ""
|
||||
_argc_index=$((_argc_index + _argc_take_args_len + 1))
|
||||
if [[ -z "${argc_path:-}" ]]; then
|
||||
argc_path="${_argc_take_args_values[0]:-}"
|
||||
else
|
||||
_argc_die "error: the argument \`--path\` cannot be used multiple times"
|
||||
fi
|
||||
;;
|
||||
--contents)
|
||||
_argc_take_args "--contents <CONTENTS>" 1 1 "-" ""
|
||||
_argc_index=$((_argc_index + _argc_take_args_len + 1))
|
||||
if [[ -z "${argc_contents:-}" ]]; then
|
||||
argc_contents="${_argc_take_args_values[0]:-}"
|
||||
else
|
||||
_argc_die "error: the argument \`--contents\` cannot be used multiple times"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
if _argc_maybe_flag_option "-" "$_argc_item"; then
|
||||
_argc_die "error: unexpected argument \`$_argc_key\` found"
|
||||
fi
|
||||
argc__positionals+=("$_argc_item")
|
||||
_argc_index=$((_argc_index + 1))
|
||||
;;
|
||||
esac
|
||||
done
|
||||
_argc_require_params "error: the following required arguments were not provided:" \
|
||||
'argc_path:--path <PATH>' 'argc_contents:--contents <CONTENTS>'
|
||||
if [[ -n "${_argc_action:-}" ]]; then
|
||||
$_argc_action
|
||||
else
|
||||
argc__fn=main
|
||||
if [[ "${argc__positionals[0]:-}" == "help" ]] && [[ "${#argc__positionals[@]}" -eq 1 ]]; then
|
||||
_argc_usage
|
||||
fi
|
||||
if [[ -z "${LLM_OUTPUT:-}" ]]; then
|
||||
export LLM_OUTPUT=/dev/stdout
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
_argc_take_args() {
|
||||
_argc_take_args_values=()
|
||||
_argc_take_args_len=0
|
||||
local param="$1" min="$2" max="$3" signs="$4" delimiter="$5"
|
||||
if [[ "$min" -eq 0 ]] && [[ "$max" -eq 0 ]]; then
|
||||
return
|
||||
fi
|
||||
local _argc_take_index=$((_argc_index + 1)) _argc_take_value
|
||||
if [[ "$_argc_item" == *=* ]]; then
|
||||
_argc_take_args_values=("${_argc_item##*=}")
|
||||
else
|
||||
while [[ $_argc_take_index -lt $_argc_len ]]; do
|
||||
_argc_take_value="${argc__args[_argc_take_index]}"
|
||||
if _argc_maybe_flag_option "$signs" "$_argc_take_value"; then
|
||||
if [[ "${#_argc_take_value}" -gt 1 ]]; then
|
||||
break
|
||||
fi
|
||||
fi
|
||||
_argc_take_args_values+=("$_argc_take_value")
|
||||
_argc_take_args_len=$((_argc_take_args_len + 1))
|
||||
if [[ "$_argc_take_args_len" -ge "$max" ]]; then
|
||||
break
|
||||
fi
|
||||
_argc_take_index=$((_argc_take_index + 1))
|
||||
done
|
||||
fi
|
||||
if [[ "${#_argc_take_args_values[@]}" -lt "$min" ]]; then
|
||||
_argc_die "error: incorrect number of values for \`$param\`"
|
||||
fi
|
||||
if [[ -n "$delimiter" ]] && [[ "${#_argc_take_args_values[@]}" -gt 0 ]]; then
|
||||
local item values arr=()
|
||||
for item in "${_argc_take_args_values[@]}"; do
|
||||
IFS="$delimiter" read -r -a values <<<"$item"
|
||||
arr+=("${values[@]}")
|
||||
done
|
||||
_argc_take_args_values=("${arr[@]}")
|
||||
fi
|
||||
}
|
||||
|
||||
_argc_require_params() {
|
||||
local message="$1" missed_envs="" item name render_name
|
||||
for item in "${@:2}"; do
|
||||
name="${item%%:*}"
|
||||
render_name="${item##*:}"
|
||||
if [[ -z "${!name:-}" ]]; then
|
||||
missed_envs="$missed_envs"$'\n'" $render_name"
|
||||
fi
|
||||
done
|
||||
if [[ -n "${missed_envs}" ]]; then
|
||||
_argc_die "$message$missed_envs"
|
||||
fi
|
||||
}
|
||||
|
||||
_argc_maybe_flag_option() {
|
||||
local signs="$1" arg="$2"
|
||||
if [[ -z "$signs" ]]; then
|
||||
return 1
|
||||
fi
|
||||
local cond=false
|
||||
if [[ "$signs" == *"+"* ]]; then
|
||||
if [[ "$arg" =~ ^\+[^+].* ]]; then
|
||||
cond=true
|
||||
fi
|
||||
elif [[ "$arg" == -* ]]; then
|
||||
if (( ${#arg} < 3 )) || [[ ! "$arg" =~ ^---.* ]]; then
|
||||
cond=true
|
||||
fi
|
||||
fi
|
||||
if [[ "$cond" == "false" ]]; then
|
||||
return 1
|
||||
fi
|
||||
local value="${arg%%=*}"
|
||||
if [[ "$value" =~ [[:space:]] ]]; then
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
_argc_die() {
|
||||
if [[ $# -eq 0 ]]; then
|
||||
cat
|
||||
else
|
||||
echo "$*" >&2
|
||||
fi
|
||||
exit 1
|
||||
}
|
||||
|
||||
_argc_run "$@"
|
||||
|
||||
# ARGC-BUILD }
|
||||
Executable
+210
@@ -0,0 +1,210 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
# @describe Remove the file or directory at the specified path.
|
||||
|
||||
# @option --path! The path of the file or directory to remove
|
||||
|
||||
# @env LLM_OUTPUT=/dev/stdout The output path
|
||||
|
||||
PROMPT_UTILS="${LLM_ROOT_DIR:-$(dirname "${BASH_SOURCE[0]}")/..}/utils/prompt-utils.sh"
|
||||
# shellcheck disable=SC1090
|
||||
source "$PROMPT_UTILS"
|
||||
|
||||
# shellcheck disable=SC2154
|
||||
main() {
|
||||
if [[ -f "$argc_path" ]]; then
|
||||
guard_path "$argc_path" "Remove '$argc_path'?"
|
||||
rm -rf "$argc_path"
|
||||
fi
|
||||
|
||||
echo "Path removed: $argc_path" >> "$LLM_OUTPUT"
|
||||
}
|
||||
|
||||
|
||||
# ARGC-BUILD {
|
||||
# This block was generated by argc (https://github.com/sigoden/argc).
|
||||
# Modifying it manually is not recommended
|
||||
|
||||
_argc_run() {
|
||||
if [[ "${1:-}" == "___internal___" ]]; then
|
||||
_argc_die "error: unsupported ___internal___ command"
|
||||
fi
|
||||
if [[ "${OS:-}" == "Windows_NT" ]] && [[ -n "${MSYSTEM:-}" ]]; then
|
||||
set -o igncr
|
||||
fi
|
||||
argc__args=("$(basename "$0" .sh)" "$@")
|
||||
argc__positionals=()
|
||||
_argc_index=1
|
||||
_argc_len="${#argc__args[@]}"
|
||||
_argc_tools=()
|
||||
_argc_parse
|
||||
if [ -n "${argc__fn:-}" ]; then
|
||||
$argc__fn "${argc__positionals[@]}"
|
||||
fi
|
||||
}
|
||||
|
||||
_argc_usage() {
|
||||
cat <<-'EOF'
|
||||
Remove the file or directory at the specified path.
|
||||
|
||||
USAGE: --path <PATH>
|
||||
|
||||
OPTIONS:
|
||||
--path <PATH> The path of the file or directory to remove
|
||||
-h, --help Print help
|
||||
-V, --version Print version
|
||||
|
||||
ENVIRONMENTS:
|
||||
LLM_OUTPUT The output path [default: /dev/stdout]
|
||||
EOF
|
||||
exit
|
||||
}
|
||||
|
||||
_argc_version() {
|
||||
echo 0.0.0
|
||||
exit
|
||||
}
|
||||
|
||||
_argc_parse() {
|
||||
local _argc_key _argc_action
|
||||
local _argc_subcmds=""
|
||||
while [[ $_argc_index -lt $_argc_len ]]; do
|
||||
_argc_item="${argc__args[_argc_index]}"
|
||||
_argc_key="${_argc_item%%=*}"
|
||||
case "$_argc_key" in
|
||||
--help | -help | -h)
|
||||
_argc_usage
|
||||
;;
|
||||
--version | -version | -V)
|
||||
_argc_version
|
||||
;;
|
||||
--)
|
||||
_argc_dash="${#argc__positionals[@]}"
|
||||
argc__positionals+=("${argc__args[@]:$((_argc_index + 1))}")
|
||||
_argc_index=$_argc_len
|
||||
break
|
||||
;;
|
||||
--path)
|
||||
_argc_take_args "--path <PATH>" 1 1 "-" ""
|
||||
_argc_index=$((_argc_index + _argc_take_args_len + 1))
|
||||
if [[ -z "${argc_path:-}" ]]; then
|
||||
argc_path="${_argc_take_args_values[0]:-}"
|
||||
else
|
||||
_argc_die "error: the argument \`--path\` cannot be used multiple times"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
if _argc_maybe_flag_option "-" "$_argc_item"; then
|
||||
_argc_die "error: unexpected argument \`$_argc_key\` found"
|
||||
fi
|
||||
argc__positionals+=("$_argc_item")
|
||||
_argc_index=$((_argc_index + 1))
|
||||
;;
|
||||
esac
|
||||
done
|
||||
_argc_require_params "error: the following required arguments were not provided:" \
|
||||
'argc_path:--path <PATH>'
|
||||
if [[ -n "${_argc_action:-}" ]]; then
|
||||
$_argc_action
|
||||
else
|
||||
argc__fn=main
|
||||
if [[ "${argc__positionals[0]:-}" == "help" ]] && [[ "${#argc__positionals[@]}" -eq 1 ]]; then
|
||||
_argc_usage
|
||||
fi
|
||||
if [[ -z "${LLM_OUTPUT:-}" ]]; then
|
||||
export LLM_OUTPUT=/dev/stdout
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
_argc_take_args() {
|
||||
_argc_take_args_values=()
|
||||
_argc_take_args_len=0
|
||||
local param="$1" min="$2" max="$3" signs="$4" delimiter="$5"
|
||||
if [[ "$min" -eq 0 ]] && [[ "$max" -eq 0 ]]; then
|
||||
return
|
||||
fi
|
||||
local _argc_take_index=$((_argc_index + 1)) _argc_take_value
|
||||
if [[ "$_argc_item" == *=* ]]; then
|
||||
_argc_take_args_values=("${_argc_item##*=}")
|
||||
else
|
||||
while [[ $_argc_take_index -lt $_argc_len ]]; do
|
||||
_argc_take_value="${argc__args[_argc_take_index]}"
|
||||
if _argc_maybe_flag_option "$signs" "$_argc_take_value"; then
|
||||
if [[ "${#_argc_take_value}" -gt 1 ]]; then
|
||||
break
|
||||
fi
|
||||
fi
|
||||
_argc_take_args_values+=("$_argc_take_value")
|
||||
_argc_take_args_len=$((_argc_take_args_len + 1))
|
||||
if [[ "$_argc_take_args_len" -ge "$max" ]]; then
|
||||
break
|
||||
fi
|
||||
_argc_take_index=$((_argc_take_index + 1))
|
||||
done
|
||||
fi
|
||||
if [[ "${#_argc_take_args_values[@]}" -lt "$min" ]]; then
|
||||
_argc_die "error: incorrect number of values for \`$param\`"
|
||||
fi
|
||||
if [[ -n "$delimiter" ]] && [[ "${#_argc_take_args_values[@]}" -gt 0 ]]; then
|
||||
local item values arr=()
|
||||
for item in "${_argc_take_args_values[@]}"; do
|
||||
IFS="$delimiter" read -r -a values <<<"$item"
|
||||
arr+=("${values[@]}")
|
||||
done
|
||||
_argc_take_args_values=("${arr[@]}")
|
||||
fi
|
||||
}
|
||||
|
||||
_argc_require_params() {
|
||||
local message="$1" missed_envs="" item name render_name
|
||||
for item in "${@:2}"; do
|
||||
name="${item%%:*}"
|
||||
render_name="${item##*:}"
|
||||
if [[ -z "${!name:-}" ]]; then
|
||||
missed_envs="$missed_envs"$'\n'" $render_name"
|
||||
fi
|
||||
done
|
||||
if [[ -n "${missed_envs}" ]]; then
|
||||
_argc_die "$message$missed_envs"
|
||||
fi
|
||||
}
|
||||
|
||||
_argc_maybe_flag_option() {
|
||||
local signs="$1" arg="$2"
|
||||
if [[ -z "$signs" ]]; then
|
||||
return 1
|
||||
fi
|
||||
local cond=false
|
||||
if [[ "$signs" == *"+"* ]]; then
|
||||
if [[ "$arg" =~ ^\+[^+].* ]]; then
|
||||
cond=true
|
||||
fi
|
||||
elif [[ "$arg" == -* ]]; then
|
||||
if (( ${#arg} < 3 )) || [[ ! "$arg" =~ ^---.* ]]; then
|
||||
cond=true
|
||||
fi
|
||||
fi
|
||||
if [[ "$cond" == "false" ]]; then
|
||||
return 1
|
||||
fi
|
||||
local value="${arg%%=*}"
|
||||
if [[ "$value" =~ [[:space:]] ]]; then
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
_argc_die() {
|
||||
if [[ $# -eq 0 ]]; then
|
||||
cat
|
||||
else
|
||||
echo "$*" >&2
|
||||
fi
|
||||
exit 1
|
||||
}
|
||||
|
||||
_argc_run "$@"
|
||||
|
||||
# ARGC-BUILD }
|
||||
Executable
+224
@@ -0,0 +1,224 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
# @describe Write the full file contents to a file at the specified path.
|
||||
|
||||
# @option --path! The path of the file to write to
|
||||
# @option --contents! The full contents to write to the file
|
||||
|
||||
# @env LLM_OUTPUT=/dev/stdout The output path
|
||||
|
||||
PROMPT_UTILS="${LLM_ROOT_DIR:-$(dirname "${BASH_SOURCE[0]}")/..}/utils/prompt-utils.sh"
|
||||
# shellcheck disable=SC1090
|
||||
source "$PROMPT_UTILS"
|
||||
|
||||
# shellcheck disable=SC2154
|
||||
main() {
|
||||
if [[ -f "$argc_path" ]]; then
|
||||
printf "%s" "$argc_contents" | git diff --no-index "$argc_path" - || true
|
||||
guard_operation "Apply changes?"
|
||||
else
|
||||
guard_path "$argc_path" "Write '$argc_path'?"
|
||||
mkdir -p "$(dirname "$argc_path")"
|
||||
fi
|
||||
|
||||
printf "%s" "$argc_contents" > "$argc_path"
|
||||
echo "The File contents were written to: $argc_path" >> "$LLM_OUTPUT"
|
||||
}
|
||||
|
||||
# ARGC-BUILD {
|
||||
# This block was generated by argc (https://github.com/sigoden/argc).
|
||||
# Modifying it manually is not recommended
|
||||
|
||||
_argc_run() {
|
||||
if [[ "${1:-}" == "___internal___" ]]; then
|
||||
_argc_die "error: unsupported ___internal___ command"
|
||||
fi
|
||||
if [[ "${OS:-}" == "Windows_NT" ]] && [[ -n "${MSYSTEM:-}" ]]; then
|
||||
set -o igncr
|
||||
fi
|
||||
argc__args=("$(basename "$0" .sh)" "$@")
|
||||
argc__positionals=()
|
||||
_argc_index=1
|
||||
_argc_len="${#argc__args[@]}"
|
||||
_argc_tools=()
|
||||
_argc_parse
|
||||
if [ -n "${argc__fn:-}" ]; then
|
||||
$argc__fn "${argc__positionals[@]}"
|
||||
fi
|
||||
}
|
||||
|
||||
_argc_usage() {
|
||||
cat <<-'EOF'
|
||||
Write the full file contents to a file at the specified path.
|
||||
|
||||
USAGE: --path <PATH> --contents <CONTENTS>
|
||||
|
||||
OPTIONS:
|
||||
--path <PATH> The path of the file to write to
|
||||
--contents <CONTENTS> The full contents to write to the file
|
||||
-h, --help Print help
|
||||
-V, --version Print version
|
||||
|
||||
ENVIRONMENTS:
|
||||
LLM_OUTPUT The output path [default: /dev/stdout]
|
||||
EOF
|
||||
exit
|
||||
}
|
||||
|
||||
_argc_version() {
|
||||
echo 0.0.0
|
||||
exit
|
||||
}
|
||||
|
||||
_argc_parse() {
|
||||
local _argc_key _argc_action
|
||||
local _argc_subcmds=""
|
||||
while [[ $_argc_index -lt $_argc_len ]]; do
|
||||
_argc_item="${argc__args[_argc_index]}"
|
||||
_argc_key="${_argc_item%%=*}"
|
||||
case "$_argc_key" in
|
||||
--help | -help | -h)
|
||||
_argc_usage
|
||||
;;
|
||||
--version | -version | -V)
|
||||
_argc_version
|
||||
;;
|
||||
--)
|
||||
_argc_dash="${#argc__positionals[@]}"
|
||||
argc__positionals+=("${argc__args[@]:$((_argc_index + 1))}")
|
||||
_argc_index=$_argc_len
|
||||
break
|
||||
;;
|
||||
--path)
|
||||
_argc_take_args "--path <PATH>" 1 1 "-" ""
|
||||
_argc_index=$((_argc_index + _argc_take_args_len + 1))
|
||||
if [[ -z "${argc_path:-}" ]]; then
|
||||
argc_path="${_argc_take_args_values[0]:-}"
|
||||
else
|
||||
_argc_die "error: the argument \`--path\` cannot be used multiple times"
|
||||
fi
|
||||
;;
|
||||
--contents)
|
||||
_argc_take_args "--contents <CONTENTS>" 1 1 "-" ""
|
||||
_argc_index=$((_argc_index + _argc_take_args_len + 1))
|
||||
if [[ -z "${argc_contents:-}" ]]; then
|
||||
argc_contents="${_argc_take_args_values[0]:-}"
|
||||
else
|
||||
_argc_die "error: the argument \`--contents\` cannot be used multiple times"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
if _argc_maybe_flag_option "-" "$_argc_item"; then
|
||||
_argc_die "error: unexpected argument \`$_argc_key\` found"
|
||||
fi
|
||||
argc__positionals+=("$_argc_item")
|
||||
_argc_index=$((_argc_index + 1))
|
||||
;;
|
||||
esac
|
||||
done
|
||||
_argc_require_params "error: the following required arguments were not provided:" \
|
||||
'argc_path:--path <PATH>' 'argc_contents:--contents <CONTENTS>'
|
||||
if [[ -n "${_argc_action:-}" ]]; then
|
||||
$_argc_action
|
||||
else
|
||||
argc__fn=main
|
||||
if [[ "${argc__positionals[0]:-}" == "help" ]] && [[ "${#argc__positionals[@]}" -eq 1 ]]; then
|
||||
_argc_usage
|
||||
fi
|
||||
if [[ -z "${LLM_OUTPUT:-}" ]]; then
|
||||
export LLM_OUTPUT=/dev/stdout
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
_argc_take_args() {
|
||||
_argc_take_args_values=()
|
||||
_argc_take_args_len=0
|
||||
local param="$1" min="$2" max="$3" signs="$4" delimiter="$5"
|
||||
if [[ "$min" -eq 0 ]] && [[ "$max" -eq 0 ]]; then
|
||||
return
|
||||
fi
|
||||
local _argc_take_index=$((_argc_index + 1)) _argc_take_value
|
||||
if [[ "$_argc_item" == *=* ]]; then
|
||||
_argc_take_args_values=("${_argc_item##*=}")
|
||||
else
|
||||
while [[ $_argc_take_index -lt $_argc_len ]]; do
|
||||
_argc_take_value="${argc__args[_argc_take_index]}"
|
||||
if _argc_maybe_flag_option "$signs" "$_argc_take_value"; then
|
||||
if [[ "${#_argc_take_value}" -gt 1 ]]; then
|
||||
break
|
||||
fi
|
||||
fi
|
||||
_argc_take_args_values+=("$_argc_take_value")
|
||||
_argc_take_args_len=$((_argc_take_args_len + 1))
|
||||
if [[ "$_argc_take_args_len" -ge "$max" ]]; then
|
||||
break
|
||||
fi
|
||||
_argc_take_index=$((_argc_take_index + 1))
|
||||
done
|
||||
fi
|
||||
if [[ "${#_argc_take_args_values[@]}" -lt "$min" ]]; then
|
||||
_argc_die "error: incorrect number of values for \`$param\`"
|
||||
fi
|
||||
if [[ -n "$delimiter" ]] && [[ "${#_argc_take_args_values[@]}" -gt 0 ]]; then
|
||||
local item values arr=()
|
||||
for item in "${_argc_take_args_values[@]}"; do
|
||||
IFS="$delimiter" read -r -a values <<<"$item"
|
||||
arr+=("${values[@]}")
|
||||
done
|
||||
_argc_take_args_values=("${arr[@]}")
|
||||
fi
|
||||
}
|
||||
|
||||
_argc_require_params() {
|
||||
local message="$1" missed_envs="" item name render_name
|
||||
for item in "${@:2}"; do
|
||||
name="${item%%:*}"
|
||||
render_name="${item##*:}"
|
||||
if [[ -z "${!name:-}" ]]; then
|
||||
missed_envs="$missed_envs"$'\n'" $render_name"
|
||||
fi
|
||||
done
|
||||
if [[ -n "${missed_envs}" ]]; then
|
||||
_argc_die "$message$missed_envs"
|
||||
fi
|
||||
}
|
||||
|
||||
_argc_maybe_flag_option() {
|
||||
local signs="$1" arg="$2"
|
||||
if [[ -z "$signs" ]]; then
|
||||
return 1
|
||||
fi
|
||||
local cond=false
|
||||
if [[ "$signs" == *"+"* ]]; then
|
||||
if [[ "$arg" =~ ^\+[^+].* ]]; then
|
||||
cond=true
|
||||
fi
|
||||
elif [[ "$arg" == -* ]]; then
|
||||
if (( ${#arg} < 3 )) || [[ ! "$arg" =~ ^---.* ]]; then
|
||||
cond=true
|
||||
fi
|
||||
fi
|
||||
if [[ "$cond" == "false" ]]; then
|
||||
return 1
|
||||
fi
|
||||
local value="${arg%%=*}"
|
||||
if [[ "$value" =~ [[:space:]] ]]; then
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
_argc_die() {
|
||||
if [[ $# -eq 0 ]]; then
|
||||
cat
|
||||
else
|
||||
echo "$*" >&2
|
||||
fi
|
||||
exit 1
|
||||
}
|
||||
|
||||
_argc_run "$@"
|
||||
|
||||
# ARGC-BUILD }
|
||||
Executable
+10
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
# @describe Get the current time.
|
||||
|
||||
# @env LLM_OUTPUT=/dev/stdout The output path
|
||||
|
||||
main() {
|
||||
date >> "$LLM_OUTPUT"
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import os
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
from urllib.parse import quote_plus
|
||||
from urllib.request import urlopen
|
||||
|
||||
|
||||
def run(
|
||||
location: str,
|
||||
llm_output: Optional[str] = None,
|
||||
) -> str:
|
||||
"""Get the current weather in a given location
|
||||
|
||||
Args:
|
||||
location (str): The city and optionally the state or country (e.g., "London", "San Francisco, CA").
|
||||
|
||||
Returns:
|
||||
str: A single-line formatted weather string from wttr.in (``format=4`` with metric units).
|
||||
"""
|
||||
url = f"https://wttr.in/{quote_plus(location)}?format=4&M"
|
||||
|
||||
with urlopen(url, timeout=10) as resp:
|
||||
weather = resp.read().decode("utf-8", errors="replace")
|
||||
|
||||
dest = llm_output if llm_output is not None else os.environ.get("LLM_OUTPUT", "/dev/stdout")
|
||||
|
||||
if dest not in {"-", "/dev/stdout"}:
|
||||
path = Path(dest)
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
with path.open("a", encoding="utf-8") as fh:
|
||||
fh.write(weather)
|
||||
else:
|
||||
pass
|
||||
|
||||
return weather
|
||||
+199
@@ -0,0 +1,199 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
# @describe Get the current weather in a given location.
|
||||
# @option --location! The city and optionally the state or country, e.g., "London", "San Francisco, CA".
|
||||
|
||||
# @env LLM_OUTPUT=/dev/stdout The output path
|
||||
|
||||
main() {
|
||||
curl -fsSL "https://wttr.in/$(echo "$argc_location" | sed 's/ /+/g')?format=4&M" \
|
||||
>> "$LLM_OUTPUT"
|
||||
}
|
||||
|
||||
# ARGC-BUILD {
|
||||
# This block was generated by argc (https://github.com/sigoden/argc).
|
||||
# Modifying it manually is not recommended
|
||||
|
||||
_argc_run() {
|
||||
if [[ "${1:-}" == "___internal___" ]]; then
|
||||
_argc_die "error: unsupported ___internal___ command"
|
||||
fi
|
||||
if [[ "${OS:-}" == "Windows_NT" ]] && [[ -n "${MSYSTEM:-}" ]]; then
|
||||
set -o igncr
|
||||
fi
|
||||
argc__args=("$(basename "$0" .sh)" "$@")
|
||||
argc__positionals=()
|
||||
_argc_index=1
|
||||
_argc_len="${#argc__args[@]}"
|
||||
_argc_tools=()
|
||||
_argc_parse
|
||||
if [ -n "${argc__fn:-}" ]; then
|
||||
$argc__fn "${argc__positionals[@]}"
|
||||
fi
|
||||
}
|
||||
|
||||
_argc_usage() {
|
||||
cat <<-'EOF'
|
||||
Get the current weather in a given location.
|
||||
|
||||
USAGE: --location <LOCATION>
|
||||
|
||||
OPTIONS:
|
||||
--location <LOCATION> The city and optionally the state or country, e.g., "London", "San Francisco, CA".
|
||||
-h, --help Print help
|
||||
-V, --version Print version
|
||||
|
||||
ENVIRONMENTS:
|
||||
LLM_OUTPUT The output path [default: /dev/stdout]
|
||||
EOF
|
||||
exit
|
||||
}
|
||||
|
||||
_argc_version() {
|
||||
echo 0.0.0
|
||||
exit
|
||||
}
|
||||
|
||||
_argc_parse() {
|
||||
local _argc_key _argc_action
|
||||
local _argc_subcmds=""
|
||||
while [[ $_argc_index -lt $_argc_len ]]; do
|
||||
_argc_item="${argc__args[_argc_index]}"
|
||||
_argc_key="${_argc_item%%=*}"
|
||||
case "$_argc_key" in
|
||||
--help | -help | -h)
|
||||
_argc_usage
|
||||
;;
|
||||
--version | -version | -V)
|
||||
_argc_version
|
||||
;;
|
||||
--)
|
||||
_argc_dash="${#argc__positionals[@]}"
|
||||
argc__positionals+=("${argc__args[@]:$((_argc_index + 1))}")
|
||||
_argc_index=$_argc_len
|
||||
break
|
||||
;;
|
||||
--location)
|
||||
_argc_take_args "--location <LOCATION>" 1 1 "-" ""
|
||||
_argc_index=$((_argc_index + _argc_take_args_len + 1))
|
||||
if [[ -z "${argc_location:-}" ]]; then
|
||||
argc_location="${_argc_take_args_values[0]:-}"
|
||||
else
|
||||
_argc_die "error: the argument \`--location\` cannot be used multiple times"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
if _argc_maybe_flag_option "-" "$_argc_item"; then
|
||||
_argc_die "error: unexpected argument \`$_argc_key\` found"
|
||||
fi
|
||||
argc__positionals+=("$_argc_item")
|
||||
_argc_index=$((_argc_index + 1))
|
||||
;;
|
||||
esac
|
||||
done
|
||||
_argc_require_params "error: the following required arguments were not provided:" \
|
||||
'argc_location:--location <LOCATION>'
|
||||
if [[ -n "${_argc_action:-}" ]]; then
|
||||
$_argc_action
|
||||
else
|
||||
argc__fn=main
|
||||
if [[ "${argc__positionals[0]:-}" == "help" ]] && [[ "${#argc__positionals[@]}" -eq 1 ]]; then
|
||||
_argc_usage
|
||||
fi
|
||||
if [[ -z "${LLM_OUTPUT:-}" ]]; then
|
||||
export LLM_OUTPUT=/dev/stdout
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
_argc_take_args() {
|
||||
_argc_take_args_values=()
|
||||
_argc_take_args_len=0
|
||||
local param="$1" min="$2" max="$3" signs="$4" delimiter="$5"
|
||||
if [[ "$min" -eq 0 ]] && [[ "$max" -eq 0 ]]; then
|
||||
return
|
||||
fi
|
||||
local _argc_take_index=$((_argc_index + 1)) _argc_take_value
|
||||
if [[ "$_argc_item" == *=* ]]; then
|
||||
_argc_take_args_values=("${_argc_item##*=}")
|
||||
else
|
||||
while [[ $_argc_take_index -lt $_argc_len ]]; do
|
||||
_argc_take_value="${argc__args[_argc_take_index]}"
|
||||
if _argc_maybe_flag_option "$signs" "$_argc_take_value"; then
|
||||
if [[ "${#_argc_take_value}" -gt 1 ]]; then
|
||||
break
|
||||
fi
|
||||
fi
|
||||
_argc_take_args_values+=("$_argc_take_value")
|
||||
_argc_take_args_len=$((_argc_take_args_len + 1))
|
||||
if [[ "$_argc_take_args_len" -ge "$max" ]]; then
|
||||
break
|
||||
fi
|
||||
_argc_take_index=$((_argc_take_index + 1))
|
||||
done
|
||||
fi
|
||||
if [[ "${#_argc_take_args_values[@]}" -lt "$min" ]]; then
|
||||
_argc_die "error: incorrect number of values for \`$param\`"
|
||||
fi
|
||||
if [[ -n "$delimiter" ]] && [[ "${#_argc_take_args_values[@]}" -gt 0 ]]; then
|
||||
local item values arr=()
|
||||
for item in "${_argc_take_args_values[@]}"; do
|
||||
IFS="$delimiter" read -r -a values <<<"$item"
|
||||
arr+=("${values[@]}")
|
||||
done
|
||||
_argc_take_args_values=("${arr[@]}")
|
||||
fi
|
||||
}
|
||||
|
||||
_argc_require_params() {
|
||||
local message="$1" missed_envs="" item name render_name
|
||||
for item in "${@:2}"; do
|
||||
name="${item%%:*}"
|
||||
render_name="${item##*:}"
|
||||
if [[ -z "${!name:-}" ]]; then
|
||||
missed_envs="$missed_envs"$'\n'" $render_name"
|
||||
fi
|
||||
done
|
||||
if [[ -n "${missed_envs}" ]]; then
|
||||
_argc_die "$message$missed_envs"
|
||||
fi
|
||||
}
|
||||
|
||||
_argc_maybe_flag_option() {
|
||||
local signs="$1" arg="$2"
|
||||
if [[ -z "$signs" ]]; then
|
||||
return 1
|
||||
fi
|
||||
local cond=false
|
||||
if [[ "$signs" == *"+"* ]]; then
|
||||
if [[ "$arg" =~ ^\+[^+].* ]]; then
|
||||
cond=true
|
||||
fi
|
||||
elif [[ "$arg" == -* ]]; then
|
||||
if (( ${#arg} < 3 )) || [[ ! "$arg" =~ ^---.* ]]; then
|
||||
cond=true
|
||||
fi
|
||||
fi
|
||||
if [[ "$cond" == "false" ]]; then
|
||||
return 1
|
||||
fi
|
||||
local value="${arg%%=*}"
|
||||
if [[ "$value" =~ [[:space:]] ]]; then
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
_argc_die() {
|
||||
if [[ $# -eq 0 ]]; then
|
||||
cat
|
||||
else
|
||||
echo "$*" >&2
|
||||
fi
|
||||
exit 1
|
||||
}
|
||||
|
||||
_argc_run "$@"
|
||||
|
||||
# ARGC-BUILD }
|
||||
Executable
+198
@@ -0,0 +1,198 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
# @meta require-tools jira
|
||||
# @describe Query for jira issues using a Jira Query Language (JQL) query
|
||||
# @option --jql-query! The Jira Query Language query to execute
|
||||
# @env LLM_OUTPUT=/dev/stdout The output path
|
||||
|
||||
main() {
|
||||
jira issue ls -q "$argc_jql_query" --plain >> "$LLM_OUTPUT"
|
||||
}
|
||||
|
||||
# ARGC-BUILD {
|
||||
# This block was generated by argc (https://github.com/sigoden/argc).
|
||||
# Modifying it manually is not recommended
|
||||
|
||||
_argc_run() {
|
||||
if [[ "${1:-}" == "___internal___" ]]; then
|
||||
_argc_die "error: unsupported ___internal___ command"
|
||||
fi
|
||||
if [[ "${OS:-}" == "Windows_NT" ]] && [[ -n "${MSYSTEM:-}" ]]; then
|
||||
set -o igncr
|
||||
fi
|
||||
argc__args=("$(basename "$0" .sh)" "$@")
|
||||
argc__positionals=()
|
||||
_argc_index=1
|
||||
_argc_len="${#argc__args[@]}"
|
||||
_argc_tools=()
|
||||
_argc_parse
|
||||
if [ -n "${argc__fn:-}" ]; then
|
||||
$argc__fn "${argc__positionals[@]}"
|
||||
fi
|
||||
}
|
||||
|
||||
_argc_usage() {
|
||||
cat <<-'EOF'
|
||||
Query for jira issues using a Jira Query Language (JQL) query
|
||||
|
||||
USAGE: --jql-query <JQL-QUERY>
|
||||
|
||||
OPTIONS:
|
||||
--jql-query <JQL-QUERY> The Jira Query Language query to execute
|
||||
-h, --help Print help
|
||||
-V, --version Print version
|
||||
|
||||
ENVIRONMENTS:
|
||||
LLM_OUTPUT The output path [default: /dev/stdout]
|
||||
EOF
|
||||
exit
|
||||
}
|
||||
|
||||
_argc_version() {
|
||||
echo 0.0.0
|
||||
exit
|
||||
}
|
||||
|
||||
_argc_parse() {
|
||||
local _argc_key _argc_action
|
||||
local _argc_subcmds=""
|
||||
while [[ $_argc_index -lt $_argc_len ]]; do
|
||||
_argc_item="${argc__args[_argc_index]}"
|
||||
_argc_key="${_argc_item%%=*}"
|
||||
case "$_argc_key" in
|
||||
--help | -help | -h)
|
||||
_argc_usage
|
||||
;;
|
||||
--version | -version | -V)
|
||||
_argc_version
|
||||
;;
|
||||
--)
|
||||
_argc_dash="${#argc__positionals[@]}"
|
||||
argc__positionals+=("${argc__args[@]:$((_argc_index + 1))}")
|
||||
_argc_index=$_argc_len
|
||||
break
|
||||
;;
|
||||
--jql-query)
|
||||
_argc_take_args "--jql-query <JQL-QUERY>" 1 1 "-" ""
|
||||
_argc_index=$((_argc_index + _argc_take_args_len + 1))
|
||||
if [[ -z "${argc_jql_query:-}" ]]; then
|
||||
argc_jql_query="${_argc_take_args_values[0]:-}"
|
||||
else
|
||||
_argc_die "error: the argument \`--jql-query\` cannot be used multiple times"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
if _argc_maybe_flag_option "-" "$_argc_item"; then
|
||||
_argc_die "error: unexpected argument \`$_argc_key\` found"
|
||||
fi
|
||||
argc__positionals+=("$_argc_item")
|
||||
_argc_index=$((_argc_index + 1))
|
||||
;;
|
||||
esac
|
||||
done
|
||||
_argc_require_params "error: the following required arguments were not provided:" \
|
||||
'argc_jql_query:--jql-query <JQL-QUERY>'
|
||||
if [[ -n "${_argc_action:-}" ]]; then
|
||||
$_argc_action
|
||||
else
|
||||
argc__fn=main
|
||||
if [[ "${argc__positionals[0]:-}" == "help" ]] && [[ "${#argc__positionals[@]}" -eq 1 ]]; then
|
||||
_argc_usage
|
||||
fi
|
||||
if [[ -z "${LLM_OUTPUT:-}" ]]; then
|
||||
export LLM_OUTPUT=/dev/stdout
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
_argc_take_args() {
|
||||
_argc_take_args_values=()
|
||||
_argc_take_args_len=0
|
||||
local param="$1" min="$2" max="$3" signs="$4" delimiter="$5"
|
||||
if [[ "$min" -eq 0 ]] && [[ "$max" -eq 0 ]]; then
|
||||
return
|
||||
fi
|
||||
local _argc_take_index=$((_argc_index + 1)) _argc_take_value
|
||||
if [[ "$_argc_item" == *=* ]]; then
|
||||
_argc_take_args_values=("${_argc_item##*=}")
|
||||
else
|
||||
while [[ $_argc_take_index -lt $_argc_len ]]; do
|
||||
_argc_take_value="${argc__args[_argc_take_index]}"
|
||||
if _argc_maybe_flag_option "$signs" "$_argc_take_value"; then
|
||||
if [[ "${#_argc_take_value}" -gt 1 ]]; then
|
||||
break
|
||||
fi
|
||||
fi
|
||||
_argc_take_args_values+=("$_argc_take_value")
|
||||
_argc_take_args_len=$((_argc_take_args_len + 1))
|
||||
if [[ "$_argc_take_args_len" -ge "$max" ]]; then
|
||||
break
|
||||
fi
|
||||
_argc_take_index=$((_argc_take_index + 1))
|
||||
done
|
||||
fi
|
||||
if [[ "${#_argc_take_args_values[@]}" -lt "$min" ]]; then
|
||||
_argc_die "error: incorrect number of values for \`$param\`"
|
||||
fi
|
||||
if [[ -n "$delimiter" ]] && [[ "${#_argc_take_args_values[@]}" -gt 0 ]]; then
|
||||
local item values arr=()
|
||||
for item in "${_argc_take_args_values[@]}"; do
|
||||
IFS="$delimiter" read -r -a values <<<"$item"
|
||||
arr+=("${values[@]}")
|
||||
done
|
||||
_argc_take_args_values=("${arr[@]}")
|
||||
fi
|
||||
}
|
||||
|
||||
_argc_require_params() {
|
||||
local message="$1" missed_envs="" item name render_name
|
||||
for item in "${@:2}"; do
|
||||
name="${item%%:*}"
|
||||
render_name="${item##*:}"
|
||||
if [[ -z "${!name:-}" ]]; then
|
||||
missed_envs="$missed_envs"$'\n'" $render_name"
|
||||
fi
|
||||
done
|
||||
if [[ -n "${missed_envs}" ]]; then
|
||||
_argc_die "$message$missed_envs"
|
||||
fi
|
||||
}
|
||||
|
||||
_argc_maybe_flag_option() {
|
||||
local signs="$1" arg="$2"
|
||||
if [[ -z "$signs" ]]; then
|
||||
return 1
|
||||
fi
|
||||
local cond=false
|
||||
if [[ "$signs" == *"+"* ]]; then
|
||||
if [[ "$arg" =~ ^\+[^+].* ]]; then
|
||||
cond=true
|
||||
fi
|
||||
elif [[ "$arg" == -* ]]; then
|
||||
if (( ${#arg} < 3 )) || [[ ! "$arg" =~ ^---.* ]]; then
|
||||
cond=true
|
||||
fi
|
||||
fi
|
||||
if [[ "$cond" == "false" ]]; then
|
||||
return 1
|
||||
fi
|
||||
local value="${arg%%=*}"
|
||||
if [[ "$value" =~ [[:space:]] ]]; then
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
_argc_die() {
|
||||
if [[ $# -eq 0 ]]; then
|
||||
cat
|
||||
else
|
||||
echo "$*" >&2
|
||||
fi
|
||||
exit 1
|
||||
}
|
||||
|
||||
_argc_run "$@"
|
||||
|
||||
# ARGC-BUILD }
|
||||
Executable
+16
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
# @describe Search arXiv using the given search query and return the top papers.
|
||||
|
||||
# @option --query! The search query.
|
||||
|
||||
# @env ARXIV_MAX_RESULTS=3 The max results to return.
|
||||
# @env LLM_OUTPUT=/dev/stdout The output path
|
||||
|
||||
main() {
|
||||
# shellcheck disable=SC2154
|
||||
encoded_query="$(jq -nr --arg q "$argc_query" '$q|@uri')"
|
||||
url="http://export.arxiv.org/api/query?search_query=all:$encoded_query&max_results=$ARXIV_MAX_RESULTS"
|
||||
curl -fsSL "$url" >> "$LLM_OUTPUT"
|
||||
}
|
||||
Executable
+29
@@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
# @describe Search Wikipedia using the given search query.
|
||||
# Use it to get detailed information about a public figure, interpretation of a complex scientific concept or in-depth connectivity of a significant historical event, etc.
|
||||
|
||||
# @option --query! The search query.
|
||||
|
||||
# @env LLM_OUTPUT=/dev/stdout The output path
|
||||
|
||||
# shellcheck disable=SC2154
|
||||
main() {
|
||||
encoded_query="$(jq -nr --arg q "$argc_query" '$q|@uri')"
|
||||
base_url="https://en.wikipedia.org/w/api.php"
|
||||
url="$base_url?action=query&list=search&srprop=&srlimit=1&limit=1&srsearch=$encoded_query&srinfo=suggestion&format=json"
|
||||
json="$(curl -fsSL "$url")"
|
||||
# suggestion="$(echo "$json" | jq -r '.query.searchinfo.suggestion // empty')"
|
||||
title="$(echo "$json" | jq -r '.query.search[0].title // empty')"
|
||||
pageid="$(echo "$json" | jq -r '.query.search[0].pageid // empty')"
|
||||
|
||||
if [[ -z "$title" || -z "$pageid" ]]; then
|
||||
echo "error: no results for '$argc_query'" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
title="$(echo "$title" | tr ' ' '_')"
|
||||
url="$base_url?action=query&prop=extracts&explaintext=&titles=$title&exintro=&format=json"
|
||||
curl -fsSL "$url" | jq -r '.query.pages["'"$pageid"'"].extract' >> "$LLM_OUTPUT"
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
# @describe Get an answer to a question using Wolfram Alpha. The input query should be in English.
|
||||
# Use it to answer user questions that require computation, detailed facts, data analysis, or complex queries.
|
||||
|
||||
# @option --query! The search/computation query to pass to Wolfram Alpha
|
||||
|
||||
# @env WOLFRAM_API_ID! Your Wolfram Alpha API ID
|
||||
# @env LLM_OUTPUT=/dev/stdout The output path
|
||||
|
||||
# shellcheck disable=SC2154
|
||||
main() {
|
||||
encoded_query="$(jq -nr --arg q "$argc_query" '$q|@uri')"
|
||||
url="https://api.wolframalpha.com/v2/query?appid=${WOLFRAM_API_ID}&input=$encoded_query&output=json&format=plaintext"
|
||||
|
||||
curl -fsSL "$url" | jq '[.queryresult | .pods[] | {title:.title, values:[.subpods[].plaintext | select(. != "")]}]' \
|
||||
>> "$LLM_OUTPUT"
|
||||
}
|
||||
Executable
+30
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
# @describe Send an email.
|
||||
# @option --recipient! The recipient of the email.
|
||||
# @option --subject! The subject of the email.
|
||||
# @option --body! The body of the email.
|
||||
|
||||
# @env EMAIL_SMTP_ADDR! The SMTP Address, e.g. smtps://smtp.gmail.com:465
|
||||
# @env EMAIL_SMTP_USER! The SMTP User, e.g. alice@gmail.com
|
||||
# @env EMAIL_SMTP_PASS! The SMTP Password
|
||||
# @env EMAIL_SENDER_NAME The sender's name
|
||||
# @env LLM_OUTPUT=/dev/stdout The output path
|
||||
|
||||
# shellcheck disable=SC2154
|
||||
main() {
|
||||
sender_name="${EMAIL_SENDER_NAME:-$(echo "$EMAIL_SMTP_USER" | awk -F'@' '{print $1}')}"
|
||||
printf "%s\n" "From: $sender_name <$EMAIL_SMTP_USER>
|
||||
To: $argc_recipient
|
||||
Subject: $argc_subject
|
||||
|
||||
$argc_body" | \
|
||||
curl -fsS --ssl-reqd \
|
||||
--url "$EMAIL_SMTP_ADDR" \
|
||||
--user "$EMAIL_SMTP_USER:$EMAIL_SMTP_PASS" \
|
||||
--mail-from "$EMAIL_SMTP_USER" \
|
||||
--mail-rcpt "$argc_recipient" \
|
||||
--upload-file -
|
||||
echo "Email sent successfully" >> "$LLM_OUTPUT"
|
||||
}
|
||||
Executable
+50
@@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
# @describe Send SMS or Twilio Messaging Channels messages using the Twilio API.
|
||||
# @option --to-number! The recipient's phone number. Prefix it with 'whatsapp:' for WhatsApp messages, e.g. whatsapp:+1234567890
|
||||
# @option --message! The content of the message to be sent
|
||||
|
||||
# @env TWILIO_ACCOUNT_SID! The twilio account sid
|
||||
# @env TWILIO_AUTH_TOKEN! The twilio auth token
|
||||
# @env TWILIO_FROM_NUMBER! The twilio from number
|
||||
# @env LLM_OUTPUT=/dev/stdout The output path
|
||||
|
||||
# shellcheck disable=SC2154
|
||||
main() {
|
||||
from_number="$TWILIO_FROM_NUMBER"
|
||||
to_number="$argc_to_number"
|
||||
|
||||
if [[ "$to_number" == 'whatsapp:'* ]]; then
|
||||
from_number="whatsapp:$from_number"
|
||||
fi
|
||||
|
||||
if [[ "$to_number" != 'whatsapp:'* && "$to_number" != '+'* ]]; then
|
||||
to_number="+$to_number"
|
||||
fi
|
||||
|
||||
res="$(curl -s -X POST "https://api.twilio.com/2010-04-01/Accounts/$TWILIO_ACCOUNT_SID/Messages.json" \
|
||||
-u "$TWILIO_ACCOUNT_SID:$TWILIO_AUTH_TOKEN" \
|
||||
-w "\n%{http_code}" \
|
||||
--data-urlencode "From=$from_number" \
|
||||
--data-urlencode "To=$to_number" \
|
||||
--data-urlencode "Body=$argc_message")"
|
||||
status="$(echo "$res" | tail -n 1)"
|
||||
body="$(echo "$res" | head -n -1)"
|
||||
|
||||
if [[ "$status" -ge 200 && "$status" -lt 300 ]]; then
|
||||
if [[ "$(echo "$body" | jq -r 'has("sid")')" == "true" ]]; then
|
||||
echo "Message sent successfully" >> "$LLM_OUTPUT"
|
||||
else
|
||||
_die "error: $body"
|
||||
fi
|
||||
else
|
||||
_die "error: $body"
|
||||
fi
|
||||
}
|
||||
|
||||
_die() {
|
||||
echo "$*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
Executable
+254
@@ -0,0 +1,254 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
# @describe Perform a web search to get up-to-date information or additional context.
|
||||
# Use this when you need current information or feel a search could provide a better answer.
|
||||
|
||||
# @option --query! The search query.
|
||||
|
||||
# @meta require-tools loki
|
||||
|
||||
# @env WEB_SEARCH_MODEL=gemini:gemini-2.5-flash The model for web-searching.
|
||||
#
|
||||
# supported loki models:
|
||||
# - gemini:gemini-2.0-*
|
||||
# - vertexai:gemini-*
|
||||
# - perplexity:*
|
||||
# - ernie:*
|
||||
# @env LLM_OUTPUT=/dev/stdout The output path
|
||||
|
||||
# shellcheck disable=SC2154
|
||||
main() {
|
||||
client="${WEB_SEARCH_MODEL%%:*}"
|
||||
|
||||
if [[ "$client" == "gemini" ]]; then
|
||||
export LOKI_PATCH_GEMINI_CHAT_COMPLETIONS='{".*":{"body":{"tools":[{"google_search":{}}]}}}'
|
||||
elif [[ "$client" == "vertexai" ]]; then
|
||||
export LOKI_PATCH_VERTEXAI_CHAT_COMPLETIONS='{
|
||||
"gemini-1.5-.*":{"body":{"tools":[{"googleSearchRetrieval":{}}]}},
|
||||
"gemini-2.0-.*":{"body":{"tools":[{"google_search":{}}]}}
|
||||
}'
|
||||
elif [[ "$client" == "ernie" ]]; then
|
||||
export LOKI_PATCH_ERNIE_CHAT_COMPLETIONS='{".*":{"body":{"web_search":{"enable":true}}}}'
|
||||
fi
|
||||
|
||||
loki -m "$WEB_SEARCH_MODEL" "$argc_query" >> "$LLM_OUTPUT"
|
||||
}
|
||||
|
||||
|
||||
# ARGC-BUILD {
|
||||
# This block was generated by argc (https://github.com/sigoden/argc).
|
||||
# Modifying it manually is not recommended
|
||||
|
||||
_argc_run() {
|
||||
if [[ "${1:-}" == "___internal___" ]]; then
|
||||
_argc_die "error: unsupported ___internal___ command"
|
||||
fi
|
||||
if [[ "${OS:-}" == "Windows_NT" ]] && [[ -n "${MSYSTEM:-}" ]]; then
|
||||
set -o igncr
|
||||
fi
|
||||
argc__args=("$(basename "$0" .sh)" "$@")
|
||||
argc__positionals=()
|
||||
_argc_index=1
|
||||
_argc_len="${#argc__args[@]}"
|
||||
_argc_tools=()
|
||||
_argc_parse
|
||||
_argc_require_tools "${_argc_tools[@]}"
|
||||
if [ -n "${argc__fn:-}" ]; then
|
||||
$argc__fn "${argc__positionals[@]}"
|
||||
fi
|
||||
}
|
||||
|
||||
_argc_usage() {
|
||||
cat <<-'EOF'
|
||||
Perform a web search to get up-to-date information or additional context.
|
||||
Use this when you need current information or feel a search could provide a better answer.
|
||||
|
||||
USAGE: --query <QUERY>
|
||||
|
||||
OPTIONS:
|
||||
--query <QUERY> The query to search for.
|
||||
-h, --help Print help
|
||||
-V, --version Print version
|
||||
|
||||
ENVIRONMENTS:
|
||||
WEB_SEARCH_MODEL
|
||||
The model for web-searching.
|
||||
|
||||
supported loki models:
|
||||
- gemini:gemini-2.0-*
|
||||
- vertexai:gemini-*
|
||||
- perplexity:*
|
||||
- ernie:*
|
||||
[default: gemini:gemini-2.5-flash]
|
||||
|
||||
LLM_OUTPUT
|
||||
The output path [default: /dev/stdout]
|
||||
EOF
|
||||
exit
|
||||
}
|
||||
|
||||
_argc_version() {
|
||||
echo 0.0.0
|
||||
exit
|
||||
}
|
||||
|
||||
_argc_parse() {
|
||||
local _argc_key _argc_action
|
||||
local _argc_subcmds=""
|
||||
while [[ $_argc_index -lt $_argc_len ]]; do
|
||||
_argc_item="${argc__args[_argc_index]}"
|
||||
_argc_key="${_argc_item%%=*}"
|
||||
case "$_argc_key" in
|
||||
--help | -help | -h)
|
||||
_argc_usage
|
||||
;;
|
||||
--version | -version | -V)
|
||||
_argc_version
|
||||
;;
|
||||
--)
|
||||
_argc_dash="${#argc__positionals[@]}"
|
||||
argc__positionals+=("${argc__args[@]:$((_argc_index + 1))}")
|
||||
_argc_index=$_argc_len
|
||||
break
|
||||
;;
|
||||
--query)
|
||||
_argc_take_args "--query <QUERY>" 1 1 "-" ""
|
||||
_argc_index=$((_argc_index + _argc_take_args_len + 1))
|
||||
if [[ -z "${argc_query:-}" ]]; then
|
||||
argc_query="${_argc_take_args_values[0]:-}"
|
||||
else
|
||||
_argc_die "error: the argument \`--query\` cannot be used multiple times"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
if _argc_maybe_flag_option "-" "$_argc_item"; then
|
||||
_argc_die "error: unexpected argument \`$_argc_key\` found"
|
||||
fi
|
||||
argc__positionals+=("$_argc_item")
|
||||
_argc_index=$((_argc_index + 1))
|
||||
;;
|
||||
esac
|
||||
done
|
||||
_argc_require_params "error: the following required arguments were not provided:" \
|
||||
'argc_query:--query <QUERY>'
|
||||
_argc_tools=(loki)
|
||||
if [[ -n "${_argc_action:-}" ]]; then
|
||||
$_argc_action
|
||||
else
|
||||
argc__fn=main
|
||||
if [[ "${argc__positionals[0]:-}" == "help" ]] && [[ "${#argc__positionals[@]}" -eq 1 ]]; then
|
||||
_argc_usage
|
||||
fi
|
||||
if [[ -z "${WEB_SEARCH_MODEL:-}" ]]; then
|
||||
export WEB_SEARCH_MODEL=gemini:gemini-2.5-flash
|
||||
fi
|
||||
if [[ -z "${LLM_OUTPUT:-}" ]]; then
|
||||
export LLM_OUTPUT=/dev/stdout
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
_argc_take_args() {
|
||||
_argc_take_args_values=()
|
||||
_argc_take_args_len=0
|
||||
local param="$1" min="$2" max="$3" signs="$4" delimiter="$5"
|
||||
if [[ "$min" -eq 0 ]] && [[ "$max" -eq 0 ]]; then
|
||||
return
|
||||
fi
|
||||
local _argc_take_index=$((_argc_index + 1)) _argc_take_value
|
||||
if [[ "$_argc_item" == *=* ]]; then
|
||||
_argc_take_args_values=("${_argc_item##*=}")
|
||||
else
|
||||
while [[ $_argc_take_index -lt $_argc_len ]]; do
|
||||
_argc_take_value="${argc__args[_argc_take_index]}"
|
||||
if _argc_maybe_flag_option "$signs" "$_argc_take_value"; then
|
||||
if [[ "${#_argc_take_value}" -gt 1 ]]; then
|
||||
break
|
||||
fi
|
||||
fi
|
||||
_argc_take_args_values+=("$_argc_take_value")
|
||||
_argc_take_args_len=$((_argc_take_args_len + 1))
|
||||
if [[ "$_argc_take_args_len" -ge "$max" ]]; then
|
||||
break
|
||||
fi
|
||||
_argc_take_index=$((_argc_take_index + 1))
|
||||
done
|
||||
fi
|
||||
if [[ "${#_argc_take_args_values[@]}" -lt "$min" ]]; then
|
||||
_argc_die "error: incorrect number of values for \`$param\`"
|
||||
fi
|
||||
if [[ -n "$delimiter" ]] && [[ "${#_argc_take_args_values[@]}" -gt 0 ]]; then
|
||||
local item values arr=()
|
||||
for item in "${_argc_take_args_values[@]}"; do
|
||||
IFS="$delimiter" read -r -a values <<<"$item"
|
||||
arr+=("${values[@]}")
|
||||
done
|
||||
_argc_take_args_values=("${arr[@]}")
|
||||
fi
|
||||
}
|
||||
|
||||
_argc_require_params() {
|
||||
local message="$1" missed_envs="" item name render_name
|
||||
for item in "${@:2}"; do
|
||||
name="${item%%:*}"
|
||||
render_name="${item##*:}"
|
||||
if [[ -z "${!name:-}" ]]; then
|
||||
missed_envs="$missed_envs"$'\n'" $render_name"
|
||||
fi
|
||||
done
|
||||
if [[ -n "${missed_envs}" ]]; then
|
||||
_argc_die "$message$missed_envs"
|
||||
fi
|
||||
}
|
||||
|
||||
_argc_maybe_flag_option() {
|
||||
local signs="$1" arg="$2"
|
||||
if [[ -z "$signs" ]]; then
|
||||
return 1
|
||||
fi
|
||||
local cond=false
|
||||
if [[ "$signs" == *"+"* ]]; then
|
||||
if [[ "$arg" =~ ^\+[^+].* ]]; then
|
||||
cond=true
|
||||
fi
|
||||
elif [[ "$arg" == -* ]]; then
|
||||
if (( ${#arg} < 3 )) || [[ ! "$arg" =~ ^---.* ]]; then
|
||||
cond=true
|
||||
fi
|
||||
fi
|
||||
if [[ "$cond" == "false" ]]; then
|
||||
return 1
|
||||
fi
|
||||
local value="${arg%%=*}"
|
||||
if [[ "$value" =~ [[:space:]] ]]; then
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
_argc_require_tools() {
|
||||
local tool missing_tools=()
|
||||
for tool in "$@"; do
|
||||
if ! command -v "$tool" >/dev/null 2>&1; then
|
||||
missing_tools+=("$tool")
|
||||
fi
|
||||
done
|
||||
if [[ "${#missing_tools[@]}" -gt 0 ]]; then
|
||||
echo "error: missing tools: ${missing_tools[*]}" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
_argc_die() {
|
||||
if [[ $# -eq 0 ]]; then
|
||||
cat
|
||||
else
|
||||
echo "$*" >&2
|
||||
fi
|
||||
exit 1
|
||||
}
|
||||
|
||||
_argc_run "$@"
|
||||
|
||||
# ARGC-BUILD }
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
# @describe Perform a web search using the Perplexity API to get up-to-date information or additional context.
|
||||
# Use this when you need current information or feel a search could provide a better answer.
|
||||
|
||||
# @option --query! The search query.
|
||||
|
||||
# @env PERPLEXITY_API_KEY! Your Perplexity API key
|
||||
# @env PERPLEXITY_WEB_SEARCH_MODEL=llama-3.1-sonar-small-128k-online The LLM model to use for the search
|
||||
# @env LLM_OUTPUT=/dev/stdout The output path
|
||||
|
||||
# shellcheck disable=SC2154
|
||||
main() {
|
||||
curl -fsS -X POST https://api.perplexity.ai/chat/completions \
|
||||
-H "authorization: Bearer $PERPLEXITY_API_KEY" \
|
||||
-H "accept: application/json" \
|
||||
-H "content-type: application/json" \
|
||||
--data '
|
||||
{
|
||||
"model": "'"$PERPLEXITY_WEB_SEARCH_MODEL"'",
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "'"$argc_query"'"
|
||||
}
|
||||
]
|
||||
}
|
||||
' | \
|
||||
jq -r '.choices[0].message.content' \
|
||||
>> "$LLM_OUTPUT"
|
||||
}
|
||||
Executable
+24
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
# @describe Perform a web search using the Tavily API to get up-to-date information or additional context.
|
||||
# Use this when you need current information or feel a search could provide a better answer.
|
||||
|
||||
# @option --query! The search query.
|
||||
|
||||
# @env TAVILY_API_KEY! Your Tavile API key
|
||||
# @env LLM_OUTPUT=/dev/stdout The output path The output path
|
||||
|
||||
# shellcheck disable=SC2154
|
||||
main() {
|
||||
curl -fsSL -X POST https://api.tavily.com/search \
|
||||
-H "content-type: application/json" \
|
||||
-d '
|
||||
{
|
||||
"api_key": "'"$TAVILY_API_KEY"'",
|
||||
"query": "'"$argc_query"'",
|
||||
"include_answer": true
|
||||
}' | \
|
||||
jq -r '.answer' >> "$LLM_OUTPUT"
|
||||
}
|
||||
|
||||
Executable
+716
@@ -0,0 +1,716 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Bash helper utilities for prompting users.
|
||||
# This is a modified version of the excellent Bash TUI toolkit
|
||||
# (https://github.com/timo-reymann/bash-tui-toolkit)
|
||||
#
|
||||
# It includes the following functions for you to use in your
|
||||
# bash tool commands:
|
||||
#
|
||||
# - password Password prompt
|
||||
# - checked Checkbox
|
||||
# - text Text input with validation
|
||||
# - list Select an option from a given list
|
||||
# - range Prompt the user for a value within a range
|
||||
# - confirm Confirmation prompt
|
||||
# - editor Open the user's preferred editor for input
|
||||
# - detect_os Detect the current OS
|
||||
# - get_opener Get the file opener for the current OS
|
||||
# - open_link Open the given link in the default browser
|
||||
# See https://github.com/timo-reymann/bash-tui-toolkit/blob/main/test.sh
|
||||
# for examples on how to use these commands
|
||||
#
|
||||
# - guard_operation Prompt for permission to run an operation
|
||||
# - guard_path Prompt for permission to perform path operations
|
||||
# - patch_file Patch a file
|
||||
# - error Log an error
|
||||
# - warn Log a warning
|
||||
# - info Log info
|
||||
# - debug Log a debug message
|
||||
# - trace Log a trace message
|
||||
# - red Output given text in red
|
||||
# - green Output given text in green
|
||||
# - gold Output given text in gold
|
||||
# - blue Output given text in blue
|
||||
# - magenta Output given text in magenta
|
||||
# - cyan Output given text in cyan
|
||||
# - white Output given text in white
|
||||
|
||||
# shellcheck disable=SC2034
|
||||
red=$(tput setaf 1)
|
||||
green=$(tput setaf 2)
|
||||
gold=$(tput setaf 3)
|
||||
blue=$(tput setaf 4)
|
||||
magenta=$(tput setaf 5)
|
||||
cyan=$(tput setaf 6)
|
||||
white=$(tput setaf 7)
|
||||
|
||||
default=$(tput sgr0)
|
||||
gray=$(tput setaf 243)
|
||||
|
||||
bold=$(tput bold)
|
||||
underlined=$(tput smul)
|
||||
|
||||
error() {
|
||||
echo -e "${red}${bold}ERROR:${default}${red} $1${default}"
|
||||
}
|
||||
|
||||
warn() {
|
||||
echo -e "${gold}${bold}WARN:${default}${gold} $1${default}"
|
||||
}
|
||||
|
||||
info() {
|
||||
echo -e "${cyan}${bold}INFO:${default}${cyan} $1${default}"
|
||||
}
|
||||
|
||||
debug() {
|
||||
echo -e "${blue}${bold}DEBUG:${default}${blue} $1${default}"
|
||||
}
|
||||
|
||||
trace() {
|
||||
echo -e "${gray}${bold}TRACE:${default}${gray} $1${default}"
|
||||
}
|
||||
|
||||
success() {
|
||||
echo -e "${green}${bold}SUCCESS:${default}${green} $1${default}"
|
||||
}
|
||||
|
||||
red() {
|
||||
echo -e "${red}$1${default}"
|
||||
}
|
||||
|
||||
green() {
|
||||
echo -e "${green}$1${default}"
|
||||
}
|
||||
|
||||
gold() {
|
||||
echo -e "${gold}$1${default}"
|
||||
}
|
||||
|
||||
blue() {
|
||||
echo -e "${blue}$1${default}"
|
||||
}
|
||||
|
||||
magenta() {
|
||||
echo -e "${magenta}$1${default}"
|
||||
}
|
||||
|
||||
cyan() {
|
||||
echo -e "${cyan}$1${default}"
|
||||
}
|
||||
|
||||
white() {
|
||||
echo -e "${white}$1${default}"
|
||||
}
|
||||
|
||||
_read_stdin() {
|
||||
read -r "$@" </dev/tty
|
||||
}
|
||||
|
||||
_get_cursor_row() {
|
||||
declare IFS=';'
|
||||
_read_stdin -sdR -p $'\E[6n' ROW COL
|
||||
echo "${ROW#*[}"
|
||||
}
|
||||
|
||||
_cursor_blink_on() {
|
||||
echo -en "\033[?25h" >&2
|
||||
}
|
||||
_cursor_blink_off() {
|
||||
echo -en "\033[?25l" >&2
|
||||
}
|
||||
|
||||
_cursor_to() {
|
||||
echo -en "\033[$1;$2H" >&2
|
||||
}
|
||||
|
||||
# shellcheck disable=SC2154
|
||||
_key_input() {
|
||||
declare ESC=$'\033'
|
||||
declare IFS=''
|
||||
_read_stdin -rsn1 a
|
||||
if [[ "$ESC" == "$a" ]]; then
|
||||
_read_stdin -rsn2 b
|
||||
fi
|
||||
|
||||
declare input="${a}${b}"
|
||||
case "$input" in
|
||||
"${ESC}[A" | "k") echo up ;;
|
||||
"${ESC}[B" | "j") echo down ;;
|
||||
"${ESC}[C" | "l") echo right ;;
|
||||
"${ESC}[D" | "h") echo left ;;
|
||||
'') echo enter ;;
|
||||
' ') echo space ;;
|
||||
esac
|
||||
}
|
||||
|
||||
_new_line_foreach_item() {
|
||||
count=0
|
||||
while [[ $count -lt $1 ]]; do
|
||||
echo "" >&2
|
||||
((count++))
|
||||
done
|
||||
}
|
||||
|
||||
_prompt_text() {
|
||||
echo -en "\033[32m?\033[0m\033[1m ${1}\033[0m " >&2
|
||||
}
|
||||
|
||||
_decrement_selected() {
|
||||
declare selected=$1
|
||||
((selected--))
|
||||
if [[ "${selected}" -lt 0 ]]; then
|
||||
selected=$(($2 - 1))
|
||||
fi
|
||||
|
||||
echo -n $selected
|
||||
}
|
||||
|
||||
_increment_selected() {
|
||||
declare selected=$1
|
||||
((selected++))
|
||||
|
||||
if [[ "${selected}" -ge "${opts_count}" ]]; then
|
||||
selected=0
|
||||
fi
|
||||
|
||||
echo -n $selected
|
||||
}
|
||||
|
||||
# shellcheck disable=SC2154
|
||||
input() {
|
||||
_prompt_text "$1"
|
||||
echo -en "\033[36m\c" >&2
|
||||
_read_stdin -r text
|
||||
echo -n "${text}"
|
||||
}
|
||||
|
||||
confirm() {
|
||||
trap "stty echo; exit" EXIT
|
||||
_prompt_text "$1 (y/N)"
|
||||
echo -en "\033[36m\c " >&2
|
||||
|
||||
declare first_row
|
||||
first_row=$(_get_cursor_row)
|
||||
declare current_row
|
||||
current_row=$((first_row - 1))
|
||||
declare result=""
|
||||
echo -n " " >&2
|
||||
|
||||
while true; do
|
||||
echo -e "\033[1D\c " >&2
|
||||
_read_stdin -n1 result
|
||||
|
||||
case "$result" in
|
||||
y | Y)
|
||||
echo -n 1
|
||||
break
|
||||
;;
|
||||
n | N | *)
|
||||
echo -n 0
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
echo -en "\033[0m" >&2
|
||||
echo "" >&2
|
||||
}
|
||||
|
||||
list() {
|
||||
_prompt_text "$1 "
|
||||
declare opts=("${@:2}")
|
||||
declare opts_count=$(($# - 1))
|
||||
|
||||
_new_line_foreach_item "${#opts[@]}"
|
||||
|
||||
declare last_row
|
||||
last_row=$(_get_cursor_row)
|
||||
declare first_row
|
||||
first_row=$((last_row - opts_count + 1))
|
||||
|
||||
trap "_cursor_blink_on; stty echo; exit" 2
|
||||
|
||||
_cursor_blink_off
|
||||
|
||||
declare selected=0
|
||||
while true; do
|
||||
declare idx=0
|
||||
for opt in "${opts[@]}"; do
|
||||
_cursor_to $((first_row + idx))
|
||||
|
||||
if [[ $idx -eq "$selected" ]]; then
|
||||
printf "\033[0m\033[36m❯\033[0m \033[36m%s\033[0m" "$opt" >&2
|
||||
else
|
||||
printf " %s" "$opt" >&2
|
||||
fi
|
||||
|
||||
((idx++))
|
||||
done
|
||||
|
||||
case $(_key_input) in
|
||||
enter) break ;;
|
||||
up) selected=$(_decrement_selected "${selected}" "${opts_count}") ;;
|
||||
down) selected=$(_increment_selected "${selected}" "${opts_count}") ;;
|
||||
esac
|
||||
done
|
||||
|
||||
echo -en "\n" >&2
|
||||
_cursor_to "${last_row}"
|
||||
_cursor_blink_on
|
||||
echo -n "${selected}"
|
||||
}
|
||||
|
||||
checkbox() {
|
||||
_prompt_text "$1"
|
||||
declare opts
|
||||
opts=("${@:2}")
|
||||
declare opts_count
|
||||
opts_count=$(($# - 1))
|
||||
|
||||
_new_line_foreach_item "${#opts[@]}"
|
||||
|
||||
declare last_row
|
||||
last_row=$(_get_cursor_row)
|
||||
declare first_row
|
||||
first_row=$((last_row - opts_count + 1))
|
||||
|
||||
trap "_cursor_blink_on; stty echo; exit" 2
|
||||
|
||||
_cursor_blink_off
|
||||
|
||||
declare selected=0
|
||||
declare checked=()
|
||||
while true; do
|
||||
declare idx=0
|
||||
for opt in "${opts[@]}"; do
|
||||
_cursor_to $((first_row + idx))
|
||||
declare icon="◯"
|
||||
|
||||
for item in "${checked[@]}"; do
|
||||
if [[ "$item" == "$idx" ]]; then
|
||||
icon="◉"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $idx -eq "$selected" ]]; then
|
||||
printf "%s \e[0m\e[36m❯\e[0m \e[36m%-50s\e[0m" "$icon" "$opt" >&2
|
||||
else
|
||||
printf "%s %-50s" "$icon" "$opt" >&2
|
||||
fi
|
||||
|
||||
((idx++))
|
||||
done
|
||||
|
||||
case $(_key_input) in
|
||||
enter) break ;;
|
||||
space)
|
||||
declare found=0
|
||||
for item in "${checked[@]}"; do
|
||||
if [[ "$item" == "$selected" ]]; then
|
||||
found=1
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ $found -eq 1 ]; then
|
||||
checked=("${checked[@]/$selected/}")
|
||||
else
|
||||
checked+=("${selected}")
|
||||
fi
|
||||
;;
|
||||
up) selected=$(_decrement_selected "${selected}" "${opts_count}") ;;
|
||||
down) selected=$(_increment_selected "${selected}" "${opts_count}") ;;
|
||||
esac
|
||||
done
|
||||
|
||||
_cursor_to "${last_row}"
|
||||
_cursor_blink_on
|
||||
IFS="" echo -n "${checked[@]}"
|
||||
}
|
||||
|
||||
password() {
|
||||
_prompt_text "$1"
|
||||
echo -en "\033[36m" >&2
|
||||
declare password=''
|
||||
declare IFS=
|
||||
|
||||
while _read_stdin -r -s -n1 char; do
|
||||
[[ -z "${char}" ]] && {
|
||||
printf '\n' >&2
|
||||
break
|
||||
}
|
||||
|
||||
if [[ "${char}" == $'\x7f' ]]; then
|
||||
if [[ "${#password}" -gt 0 ]]; then
|
||||
password="${password%?}"
|
||||
echo -en '\b \b' >&2
|
||||
fi
|
||||
else
|
||||
password+=$char
|
||||
echo -en '*' >&2
|
||||
fi
|
||||
done
|
||||
|
||||
echo -en "\e[0m" >&2
|
||||
echo -n "${password}"
|
||||
}
|
||||
|
||||
editor() {
|
||||
tmpfile=$(mktemp)
|
||||
_prompt_text "$1"
|
||||
echo "" >&2
|
||||
"${EDITOR:-vi}" "${tmpfile}" >/dev/tty
|
||||
echo -en "\033[36m" >&2
|
||||
sed -e 's/^/ /' "${tmpfile}" >&2
|
||||
echo -en "\033[0m" >&2
|
||||
cat "${tmpfile}"
|
||||
}
|
||||
|
||||
with_validate() {
|
||||
while true; do
|
||||
declare val
|
||||
val="$(eval "$1")"
|
||||
|
||||
if ($2 "$val" >/dev/null); then
|
||||
echo "$val"
|
||||
break
|
||||
else
|
||||
show_error "$($2 "$val")"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
range() {
|
||||
declare min="$2"
|
||||
declare current="$3"
|
||||
declare max="$4"
|
||||
declare selected="${current}"
|
||||
declare max_len_current
|
||||
max_len_current=0
|
||||
|
||||
if [[ "${#min}" -gt "${#max}" ]]; then
|
||||
max_len_current="${#min}"
|
||||
else
|
||||
max_len_current="${#max}"
|
||||
fi
|
||||
|
||||
declare padding
|
||||
padding="$(printf "%-${max_len_current}s" "")"
|
||||
declare first_row
|
||||
first_row=$(_get_cursor_row)
|
||||
declare current_row
|
||||
current_row=$((first_row - 1))
|
||||
|
||||
trap "_cursor_blink_on; stty echo; exit" 2
|
||||
|
||||
_cursor_blink_off
|
||||
|
||||
_check_range() {
|
||||
val=$1
|
||||
|
||||
if [[ "$val" -gt "$max" ]]; then
|
||||
val=$min
|
||||
elif [[ "$val" -lt "$min" ]]; then
|
||||
val=$max
|
||||
fi
|
||||
|
||||
echo "$val"
|
||||
}
|
||||
|
||||
while true; do
|
||||
_prompt_text "$1"
|
||||
printf "\033[37m%s\033[0m \033[1;90m❮\033[0m \033[36m%s%s\033[0m \033[1;90m❯\033[0m \033[37m%s\033[0m\n" "$min" "${padding:${#selected}}" "$selected" "$max" >&2
|
||||
|
||||
case $(_key_input) in
|
||||
enter)
|
||||
break
|
||||
;;
|
||||
left)
|
||||
selected="$(_check_range $((selected - 1)))"
|
||||
;;
|
||||
right)
|
||||
selected="$(_check_range $((selected + 1)))"
|
||||
;;
|
||||
esac
|
||||
|
||||
_cursor_to "$current_row"
|
||||
done
|
||||
|
||||
echo "$selected"
|
||||
}
|
||||
|
||||
validate_present() {
|
||||
if [ "$1" != "" ]; then
|
||||
return 0
|
||||
else
|
||||
error "Please specify the value"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
show_error() {
|
||||
echo -e "\033[91;1m✘ $1\033[0m" >&2
|
||||
}
|
||||
|
||||
show_success() {
|
||||
echo -e "\033[92;1m✔ $1\033[0m" >&2
|
||||
}
|
||||
|
||||
detect_os() {
|
||||
case "$OSTYPE" in
|
||||
solaris*) echo "solaris" ;;
|
||||
darwin*) echo "macos" ;;
|
||||
linux*) echo "linux" ;;
|
||||
bsd*) echo "bsd" ;;
|
||||
msys*) echo "windows" ;;
|
||||
cygwin*) echo "windows" ;;
|
||||
*) echo "unknown" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
get_opener() {
|
||||
declare cmd
|
||||
|
||||
case "$(detect_os)" in
|
||||
macos) cmd="open" ;;
|
||||
linux) cmd="xdg-open" ;;
|
||||
windows) cmd="start" ;;
|
||||
*) cmd="" ;;
|
||||
esac
|
||||
|
||||
echo "$cmd"
|
||||
}
|
||||
|
||||
open_link() {
|
||||
cmd="$(get_opener)"
|
||||
|
||||
if [[ "$cmd" == "" ]]; then
|
||||
error "Your platform is not supported for opening links."
|
||||
red "Please open the following URL in your preferred browser:"
|
||||
red " ${1}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
$cmd "$1"
|
||||
|
||||
if [[ $? -eq 1 ]]; then
|
||||
error "Failed to open your browser."
|
||||
red "Please open the following URL in your browser:"
|
||||
red "${1}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
guard_operation() {
|
||||
if [[ -t 1 ]]; then
|
||||
ans="$(confirm "${1:-Are you sure you want to continue?}")"
|
||||
|
||||
if [[ "$ans" == 0 ]]; then
|
||||
error "Operation aborted!" 2>&1
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Here is an example of a patch block that can be applied to modify the file to request the user's name:
|
||||
# --- a/hello.py
|
||||
# +++ b/hello.py
|
||||
# \@@ ... @@
|
||||
# def hello():
|
||||
# - print("Hello World")
|
||||
# + name = input("What is your name? ")
|
||||
# + print(f"Hello {name}")
|
||||
patch_file() {
|
||||
awk '
|
||||
FNR == NR {
|
||||
lines[FNR] = $0
|
||||
next;
|
||||
}
|
||||
|
||||
{
|
||||
patchLines[FNR] = $0
|
||||
}
|
||||
|
||||
END {
|
||||
totalPatchLines=length(patchLines)
|
||||
totalLines = length(lines)
|
||||
patchLineIndex = 1
|
||||
|
||||
mode = "none"
|
||||
|
||||
while (patchLineIndex <= totalPatchLines) {
|
||||
line = patchLines[patchLineIndex]
|
||||
|
||||
if (line ~ /^--- / || line ~ /^\+\+\+ /) {
|
||||
patchLineIndex++
|
||||
continue
|
||||
}
|
||||
|
||||
if (line ~ /^@@ /) {
|
||||
mode = "hunk"
|
||||
hunkIndex++
|
||||
patchLineIndex++
|
||||
continue
|
||||
}
|
||||
|
||||
if (mode == "hunk") {
|
||||
while (patchLineIndex <= totalPatchLines && line ~ /^[-+ ]|^\s*$/ && line !~ /^--- /) {
|
||||
sanitizedLine = substr(line, 2)
|
||||
|
||||
if (line !~ /^\+/) {
|
||||
hunkTotalOriginalLines[hunkIndex]++;
|
||||
hunkOriginalLines[hunkIndex,hunkTotalOriginalLines[hunkIndex]] = sanitizedLine
|
||||
}
|
||||
|
||||
if (line !~ /^-/) {
|
||||
hunkTotalUpdatedLines[hunkIndex]++;
|
||||
hunkUpdatedLines[hunkIndex,hunkTotalUpdatedLines[hunkIndex]] = sanitizedLine
|
||||
}
|
||||
|
||||
patchLineIndex++
|
||||
line = patchLines[patchLineIndex]
|
||||
}
|
||||
|
||||
mode = "none"
|
||||
} else {
|
||||
patchLineIndex++
|
||||
}
|
||||
}
|
||||
|
||||
if (hunkIndex == 0) {
|
||||
print "error: no patch" > "/dev/stderr"
|
||||
exit 1
|
||||
}
|
||||
|
||||
totalHunks = hunkIndex
|
||||
hunkIndex = 1
|
||||
|
||||
for (lineIndex = 1; lineIndex <= totalLines; lineIndex++) {
|
||||
line = lines[lineIndex]
|
||||
nextLineIndex = 0
|
||||
|
||||
if (hunkIndex <= totalHunks && line == hunkOriginalLines[hunkIndex,1]) {
|
||||
nextLineIndex = lineIndex + 1
|
||||
|
||||
for (i = 2; i <= hunkTotalOriginalLines[hunkIndex]; i++) {
|
||||
if (lines[nextLineIndex] != hunkOriginalLines[hunkIndex,i]) {
|
||||
nextLineIndex = 0
|
||||
break
|
||||
}
|
||||
|
||||
nextLineIndex++
|
||||
}
|
||||
}
|
||||
|
||||
if (nextLineIndex > 0) {
|
||||
for (i = 1; i <= hunkTotalUpdatedLines[hunkIndex]; i++) {
|
||||
print hunkUpdatedLines[hunkIndex,i]
|
||||
}
|
||||
|
||||
hunkIndex++
|
||||
lineIndex = nextLineIndex - 1;
|
||||
} else {
|
||||
print line
|
||||
}
|
||||
}
|
||||
|
||||
if (hunkIndex != totalHunks + 1) {
|
||||
print "error: unable to apply patch" > "/dev/stderr"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
function inspectHunks() {
|
||||
print "/* Begin inspecting hunks"
|
||||
|
||||
for (i = 1; i <= totalHunks; i++) {
|
||||
print ">>>>>> Original"
|
||||
|
||||
for (j = 1; j <= hunkTotalOriginalLines[i]; j++) {
|
||||
print hunkOriginalLines[i,j]
|
||||
}
|
||||
|
||||
print "======"
|
||||
|
||||
for (j = 1; j <= hunkTotalUpdatedLines[i]; j++) {
|
||||
print hunkUpdatedLines[i,j]
|
||||
}
|
||||
|
||||
print "<<<<<< Updated"
|
||||
}
|
||||
|
||||
print "End inspecting hunks */\n"
|
||||
}' "$1" "$2"
|
||||
}
|
||||
|
||||
guard_path() {
|
||||
if [[ "$#" -ne 2 ]]; then
|
||||
echo "Usage: guard_path <path> <confirmation_prompt>" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -t 1 ]]; then
|
||||
path="$(_to_real_path "$1")"
|
||||
confirmation_prompt="$2"
|
||||
|
||||
if [[ ! "$path" == "$(pwd)"* ]]; then
|
||||
ans="$(confirm "$confirmation_prompt")"
|
||||
|
||||
if [[ "$ans" == 0 ]]; then
|
||||
error "Operation aborted!" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
_to_real_path() {
|
||||
path="$1"
|
||||
|
||||
if [[ $OS == "Windows_NT" ]]; then
|
||||
path="$(cygpath -u "$path")"
|
||||
fi
|
||||
|
||||
awk -v path="$path" -v pwd="$PWD" '
|
||||
BEGIN {
|
||||
if (path !~ /^\//) {
|
||||
path = pwd "/" path
|
||||
}
|
||||
|
||||
if (path ~ /\/\.{1,2}?$/) {
|
||||
isDir = 1
|
||||
}
|
||||
|
||||
split(path, parts, "/")
|
||||
newPartsLength = 0
|
||||
|
||||
for (i = 1; i <= length(parts); i++) {
|
||||
part = parts[i]
|
||||
if (part == "..") {
|
||||
if (newPartsLength > 0) {
|
||||
delete newParts[newPartsLength--]
|
||||
}
|
||||
} else if (part != "." && part != "") {
|
||||
newParts[++newPartsLength] = part
|
||||
}
|
||||
}
|
||||
|
||||
if (isDir == 1 || newPartsLength == 0) {
|
||||
newParts[++newPartsLength] = ""
|
||||
}
|
||||
|
||||
printf "/"
|
||||
|
||||
for (i = 1; i <= newPartsLength; i++) {
|
||||
newPart = newParts[i]
|
||||
printf newPart
|
||||
if (i < newPartsLength) {
|
||||
printf "/"
|
||||
}
|
||||
}
|
||||
}'
|
||||
}
|
||||
Reference in New Issue
Block a user