feat: adjust the way of returning data to LLM (#69)

This commit is contained in:
sigoden
2024-07-10 18:53:32 +08:00
committed by GitHub
parent 01e07c0cc0
commit 732eae532c
37 changed files with 218 additions and 142 deletions
+7 -33
View File
@@ -362,39 +362,12 @@ test@tool() {
declarations_file="$TMP_DIR/functions.json" declarations_file="$TMP_DIR/functions.json"
argc list@tool > "$names_file" argc list@tool > "$names_file"
argc build@tool --names-file "$names_file" --declarations-file "$declarations_file" argc build@tool --names-file "$names_file" --declarations-file "$declarations_file"
test-execute-code-tools test-demo@tool
}
# @cmd Test maybe_execute_* tools
# @alias tool:test-execute-code
test-execute-code-tools() {
if _is_win; then
ext=".cmd"
fi
test_cases=( \
'sh#execute_command#{"command":"echo \"✓\""}' \
'js#execute_js_code#{"code":"console.log(\"✓\")"}' \
'py#execute_py_code#{"code":"print(\"✓\")"}' \
)
for test_case in "${test_cases[@]}"; do
IFS='#' read -r lang tool_name data <<<"${test_case}"
cmd="$(_lang_to_cmd "$lang")"
if command -v "$cmd" &> /dev/null; then
cmd_path="$BIN_DIR/$tool_name$ext"
echo -n "Test $cmd_path: "
"$cmd_path" "$data"
if ! _is_win; then
echo -n "Test $cmd scripts/run-tool.$lang $tool_name: "
"$cmd" "scripts/run-tool.$lang" "$tool_name" "$data"
fi
fi
done
} }
# @cmd Test demo tools # @cmd Test demo tools
# @alias tool:test-demo # @alias tool:test-demo
test-demo-tools() { test-demo@tool() {
for item in "${LANG_CMDS[@]}"; do for item in "${LANG_CMDS[@]}"; do
lang="${item%:*}" lang="${item%:*}"
tool="demo_$lang.$lang" tool="demo_$lang.$lang"
@@ -429,22 +402,23 @@ test@agent() {
names_file="$tmp_dir/agents.txt" names_file="$tmp_dir/agents.txt"
argc list@agent > "$names_file" argc list@agent > "$names_file"
argc build@agent --names-file "$names_file" argc build@agent --names-file "$names_file"
test-demo-agents test-demo@agent
} }
# @cmd Test demo agents # @cmd Test demo agents
# @alias agent:test-demo # @alias agent:test-demo
test-demo-agents() { test-demo@agent() {
echo "Test demo agent:" echo "---- Test demo agent ---"
argc run@agent demo get_sysinfo '{}' argc run@agent demo get_sysinfo '{}'
for item in "${LANG_CMDS[@]}"; do for item in "${LANG_CMDS[@]}"; do
cmd="${item#*:}" cmd="${item#*:}"
lang="${item%:*}" lang="${item%:*}"
echo "Test agents/demo/tools.$lang:" echo "---- Test agents/demo/tools.$lang ---"
if [[ "$cmd" == "sh" ]]; then if [[ "$cmd" == "sh" ]]; then
"$(argc --argc-shell-path)" ./scripts/run-agent.sh demo get_sysinfo '{}' "$(argc --argc-shell-path)" ./scripts/run-agent.sh demo get_sysinfo '{}'
elif command -v "$cmd" &> /dev/null; then elif command -v "$cmd" &> /dev/null; then
$cmd ./scripts/run-agent.$lang demo get_sysinfo '{}' $cmd ./scripts/run-agent.$lang demo get_sysinfo '{}'
echo
fi fi
done done
} }
+3 -3
View File
@@ -77,7 +77,7 @@ set -e
# @option --command! The command to execute. # @option --command! The command to execute.
main() { main() {
eval "$argc_command" eval "$argc_command" >> "$LLM_OUTPUT"
} }
eval "$(argc --argc-eval "$0" "$@")" eval "$(argc --argc-eval "$0" "$@")"
@@ -95,7 +95,7 @@ Create a new javascript in the [./tools/](./tools/) directory (.e.g. `may_execut
* @param {Args} args * @param {Args} args
*/ */
exports.main = function main({ code }) { exports.main = function main({ code }) {
eval(code); return eval(code);
} }
``` ```
@@ -110,7 +110,7 @@ def main(code: str):
Args: Args:
code: Python code to execute, such as `print("hello world")` code: Python code to execute, such as `print("hello world")`
""" """
exec(code) return exec(code)
``` ```
+1 -2
View File
@@ -4,6 +4,5 @@ const os = require("node:os");
*/ */
exports.get_sysinfo = function getSysinfo() { exports.get_sysinfo = function getSysinfo() {
return `OS: ${os.type()} return `OS: ${os.type()}
Arch: ${os.arch()} Arch: ${os.arch()}`
User: ${process.env["USER"]}`
} }
-1
View File
@@ -8,5 +8,4 @@ def get_sysinfo():
return "\n".join([ return "\n".join([
f"OS: {platform.system()}", f"OS: {platform.system()}",
f"Arch: {platform.machine()}", f"Arch: {platform.machine()}",
f"User: {os.environ.get('USER')}"
]) ])
+4 -3
View File
@@ -3,9 +3,10 @@ set -e
# @cmd Get the system info # @cmd Get the system info
get_sysinfo() { get_sysinfo() {
echo "OS: $(uname)" cat <<EOF >> "$LLM_OUTPUT"
echo "Arch: $(arch)" OS: $(uname)
echo "User: $USER" Arch: $(arch)
EOF
} }
# See more details at https://github.com/sigoden/argc # See more details at https://github.com/sigoden/argc
+7 -7
View File
@@ -17,7 +17,7 @@ add_todo() {
--arg new_desc "$argc_desc" \ --arg new_desc "$argc_desc" \
'. += [{"id": $new_id | tonumber, "desc": $new_desc}]' \ '. += [{"id": $new_id | tonumber, "desc": $new_desc}]' \
> "$todos_file" > "$todos_file"
echo "Successfully added todo id=$num" echo "Successfully added todo id=$num" >> "$LLM_OUTPUT"
} }
# @cmd Delete an existing todo item # @cmd Delete an existing todo item
@@ -29,9 +29,9 @@ del_todo() {
echo "$data" | \ echo "$data" | \
jq --arg id $argc_id '[.[] | select(.id != ($id | tonumber))]' \ jq --arg id $argc_id '[.[] | select(.id != ($id | tonumber))]' \
> "$todos_file" > "$todos_file"
echo "Successfully deleted todo id=$argc_id" echo "Successfully deleted todo id=$argc_id" >> "$LLM_OUTPUT"
else else
echo "Empty todo list" echo "Empty todo list" >> "$LLM_OUTPUT"
fi fi
} }
@@ -39,9 +39,9 @@ del_todo() {
list_todos() { list_todos() {
todos_file="$(_get_todos_file)" todos_file="$(_get_todos_file)"
if [[ -f "$todos_file" ]]; then if [[ -f "$todos_file" ]]; then
cat "$todos_file" cat "$todos_file" >> "$LLM_OUTPUT"
else else
echo '[]' echo '[]' >> "$LLM_OUTPUT"
fi fi
} }
@@ -49,9 +49,9 @@ list_todos() {
clear_todos() { clear_todos() {
todos_file="$(_get_todos_file)" todos_file="$(_get_todos_file)"
if [[ -f "$todos_file" ]]; then if [[ -f "$todos_file" ]]; then
rm -rf "$todos_file" rm -rf "$todos_file" >> "$LLM_OUTPUT"
fi fi
echo "Successfully deleted entry todo list" echo "Successfully deleted entry todo list" >> "$LLM_OUTPUT"
} }
_argc_before() { _argc_before() {
+19 -7
View File
@@ -49,11 +49,19 @@ function parseRawData(data) {
} }
function setupEnv(rootDir, agentName) { function setupEnv(rootDir, agentName) {
process.env["LLM_ROOT_DIR"] = rootDir;
loadEnv(path.resolve(rootDir, ".env")); loadEnv(path.resolve(rootDir, ".env"));
process.env["LLM_ROOT_DIR"] = rootDir;
process.env["LLM_AGENT_NAME"] = agentName; process.env["LLM_AGENT_NAME"] = agentName;
process.env["LLM_AGENT_ROOT_DIR"] = path.resolve(rootDir, "agents", agentName); process.env["LLM_AGENT_ROOT_DIR"] = path.resolve(
process.env["LLM_AGENT_CACHE_DIR"] = path.resolve(rootDir, "cache", agentName); rootDir,
"agents",
agentName,
);
process.env["LLM_AGENT_CACHE_DIR"] = path.resolve(
rootDir,
"cache",
agentName,
);
} }
function loadEnv(filePath) { function loadEnv(filePath) {
@@ -84,22 +92,26 @@ async function run(agentPath, agentFunc, agentData) {
throw new Error(`Not module function '${agentFunc}' at '${agentPath}'`); throw new Error(`Not module function '${agentFunc}' at '${agentPath}'`);
} }
const value = await mod[agentFunc](agentData); const value = await mod[agentFunc](agentData);
dumpValue(value); returnToLLM(value);
} }
function dumpValue(value) { function returnToLLM(value) {
if (value === null || value === undefined) { if (value === null || value === undefined) {
return; return;
} }
let writer = process.stdout;
if (process.env["LLM_OUTPUT"]) {
writer = fs.createWriteStream(process.env["LLM_OUTPUT"]);
}
const type = typeof value; const type = typeof value;
if (type === "string" || type === "number" || type === "boolean") { if (type === "string" || type === "number" || type === "boolean") {
console.log(value); writer.write(value);
} else if (type === "object") { } else if (type === "object") {
const proto = Object.prototype.toString.call(value); const proto = Object.prototype.toString.call(value);
if (proto === "[object Object]" || proto === "[object Array]") { if (proto === "[object Object]" || proto === "[object Array]") {
const valueStr = JSON.stringify(value, null, 2); const valueStr = JSON.stringify(value, null, 2);
require("assert").deepStrictEqual(value, JSON.parse(valueStr)); require("assert").deepStrictEqual(value, JSON.parse(valueStr));
console.log(valueStr); writer.write(value);
} }
} }
} }
+10 -5
View File
@@ -50,8 +50,8 @@ def parse_argv(this_file_name):
def setup_env(root_dir, agent_name): def setup_env(root_dir, agent_name):
os.environ["LLM_ROOT_DIR"] = root_dir
load_env(os.path.join(root_dir, ".env")) load_env(os.path.join(root_dir, ".env"))
os.environ["LLM_ROOT_DIR"] = root_dir
os.environ["LLM_AGENT_NAME"] = agent_name os.environ["LLM_AGENT_NAME"] = agent_name
os.environ["LLM_AGENT_ROOT_DIR"] = os.path.join(root_dir, "agents", agent_name) os.environ["LLM_AGENT_ROOT_DIR"] = os.path.join(root_dir, "agents", agent_name)
os.environ["LLM_AGENT_CACHE_DIR"] = os.path.join(root_dir, "cache", agent_name) os.environ["LLM_AGENT_CACHE_DIR"] = os.path.join(root_dir, "cache", agent_name)
@@ -85,20 +85,25 @@ def run(agent_path, agent_func, agent_data):
raise Exception(f"Not module function '{agent_func}' at '{agent_path}'") raise Exception(f"Not module function '{agent_func}' at '{agent_path}'")
value = getattr(mod, agent_func)(**agent_data) value = getattr(mod, agent_func)(**agent_data)
dump_value(value) return_to_llm(value)
def dump_value(value): def return_to_llm(value):
if value is None: if value is None:
return return
if "LLM_OUTPUT" in os.environ:
writer = open(os.environ["LLM_OUTPUT"], "w")
else:
writer = sys.stdout
value_type = type(value).__name__ value_type = type(value).__name__
if value_type in ("str", "int", "float", "bool"): if value_type in ("str", "int", "float", "bool"):
print(value) writer.write(value)
elif value_type == "dict" or value_type == "list": elif value_type == "dict" or value_type == "list":
value_str = json.dumps(value, indent=2) value_str = json.dumps(value, indent=2)
assert value == json.loads(value_str) assert value == json.loads(value_str)
print(value_str) writer.write(value_str)
if __name__ == "__main__": if __name__ == "__main__":
+36 -14
View File
@@ -2,16 +2,16 @@
set -e set -e
main() { main() {
this_file_name=run-agent.sh
parse_argv "$@"
root_dir="$(cd -- "$( dirname -- "${BASH_SOURCE[0]}" )/.." &> /dev/null && pwd)" root_dir="$(cd -- "$( dirname -- "${BASH_SOURCE[0]}" )/.." &> /dev/null && pwd)"
self_name=run-agent.sh
parse_argv "$@"
setup_env setup_env
agent_tools_path="$root_dir/agents/$agent_name/tools.sh" tools_path="$root_dir/agents/$agent_name/tools.sh"
run run
} }
parse_argv() { parse_argv() {
if [[ "$0" == *"$this_file_name" ]]; then if [[ "$0" == *"$self_name" ]]; then
agent_name="$1" agent_name="$1"
agent_func="$2" agent_func="$2"
agent_data="$3" agent_data="$3"
@@ -26,29 +26,43 @@ parse_argv() {
} }
setup_env() { setup_env() {
load_env "$root_dir/.env"
export LLM_ROOT_DIR="$root_dir" export LLM_ROOT_DIR="$root_dir"
if [[ -f "$LLM_ROOT_DIR/.env" ]]; then
set -o allexport && source "$LLM_ROOT_DIR/.env" && set +o allexport
fi
export LLM_AGENT_NAME="$agent_name" export LLM_AGENT_NAME="$agent_name"
export LLM_AGENT_ROOT_DIR="$LLM_ROOT_DIR/agents/$agent_name" export LLM_AGENT_ROOT_DIR="$LLM_ROOT_DIR/agents/$agent_name"
export LLM_AGENT_CACHE_DIR="$LLM_ROOT_DIR/cache/$agent_name" export LLM_AGENT_CACHE_DIR="$LLM_ROOT_DIR/cache/$agent_name"
} }
load_env() {
local env_file="$1" env_vars
if [[ -f "$env_file" ]]; then
while IFS='=' read -r key value; do
if [[ "$key" == $'#'* ]] || [[ -z "$key" ]]; then
continue
fi
if [[ -z "${!key+x}" ]]; then
env_vars="$env_vars $key=$value"
fi
done < "$env_file"
if [[ -n "$env_vars" ]]; then
eval "export $env_vars"
fi
fi
}
run() { run() {
if [[ -z "$agent_data" ]]; then if [[ -z "$agent_data" ]]; then
die "No JSON data" die "No JSON data"
fi fi
_jq=jq
if [[ "$OS" == "Windows_NT" ]]; then if [[ "$OS" == "Windows_NT" ]]; then
_jq="jq -b" set -o igncr
agent_tools_path="$(cygpath -w "$agent_tools_path")" tools_path="$(cygpath -w "$tools_path")"
fi fi
data="$( data="$(
echo "$agent_data" | \ echo "$agent_data" | \
$_jq -r ' jq -r '
to_entries | .[] | to_entries | .[] |
(.key | split("_") | join("-")) as $key | (.key | split("_") | join("-")) as $key |
if .value | type == "array" then if .value | type == "array" then
@@ -65,10 +79,18 @@ run() {
if [[ "$line" == '--'* ]]; then if [[ "$line" == '--'* ]]; then
args+=("$line") args+=("$line")
else else
args+=("$(echo "$line" | $_jq -r '.')") args+=("$(echo "$line" | jq -r '.')")
fi fi
done <<< "$data" done <<< "$data"
"$agent_tools_path" "$agent_func" "${args[@]}" no_llm_output=0
if [[ -z "$LLM_OUTPUT" ]]; then
no_llm_output=1
export LLM_OUTPUT="$(mktemp)"
fi
"$tools_path" "$agent_func" "${args[@]}"
if [[ "$no_llm_output" -eq 1 ]]; then
cat "$LLM_OUTPUT"
fi
} }
die() { die() {
+9 -5
View File
@@ -46,8 +46,8 @@ function parseRawData(data) {
} }
function setupEnv(rootDir, toolName) { function setupEnv(rootDir, toolName) {
process.env["LLM_ROOT_DIR"] = rootDir;
loadEnv(path.resolve(rootDir, ".env")); loadEnv(path.resolve(rootDir, ".env"));
process.env["LLM_ROOT_DIR"] = rootDir;
process.env["LLM_TOOL_NAME"] = toolName; process.env["LLM_TOOL_NAME"] = toolName;
process.env["LLM_TOOL_CACHE_DIR"] = path.resolve(rootDir, "cache", toolName); process.env["LLM_TOOL_CACHE_DIR"] = path.resolve(rootDir, "cache", toolName);
} }
@@ -80,22 +80,26 @@ async function run(toolPath, toolFunc, toolData) {
throw new Error(`Not module function '${toolFunc}' at '${toolPath}'`); throw new Error(`Not module function '${toolFunc}' at '${toolPath}'`);
} }
const value = await mod[toolFunc](toolData); const value = await mod[toolFunc](toolData);
dumpValue(value); returnToLLM(value);
} }
function dumpValue(value) { function returnToLLM(value) {
if (value === null || value === undefined) { if (value === null || value === undefined) {
return; return;
} }
let writer = process.stdout;
if (process.env["LLM_OUTPUT"]) {
writer = fs.createWriteStream(process.env["LLM_OUTPUT"]);
}
const type = typeof value; const type = typeof value;
if (type === "string" || type === "number" || type === "boolean") { if (type === "string" || type === "number" || type === "boolean") {
console.log(value); writer.write(value);
} else if (type === "object") { } else if (type === "object") {
const proto = Object.prototype.toString.call(value); const proto = Object.prototype.toString.call(value);
if (proto === "[object Object]" || proto === "[object Array]") { if (proto === "[object Object]" || proto === "[object Array]") {
const valueStr = JSON.stringify(value, null, 2); const valueStr = JSON.stringify(value, null, 2);
require("assert").deepStrictEqual(value, JSON.parse(valueStr)); require("assert").deepStrictEqual(value, JSON.parse(valueStr));
console.log(valueStr); writer.write(value);
} }
} }
} }
+10 -5
View File
@@ -47,8 +47,8 @@ def parse_argv(this_file_name):
def setup_env(root_dir, tool_name): def setup_env(root_dir, tool_name):
os.environ["LLM_ROOT_DIR"] = root_dir
load_env(os.path.join(root_dir, ".env")) load_env(os.path.join(root_dir, ".env"))
os.environ["LLM_ROOT_DIR"] = root_dir
os.environ["LLM_TOOL_NAME"] = tool_name os.environ["LLM_TOOL_NAME"] = tool_name
os.environ["LLM_TOOL_CACHE_DIR"] = os.path.join(root_dir, "cache", tool_name) os.environ["LLM_TOOL_CACHE_DIR"] = os.path.join(root_dir, "cache", tool_name)
@@ -81,20 +81,25 @@ def run(tool_path, tool_func, tool_data):
raise Exception(f"Not module function '{tool_func}' at '{tool_path}'") raise Exception(f"Not module function '{tool_func}' at '{tool_path}'")
value = getattr(mod, tool_func)(**tool_data) value = getattr(mod, tool_func)(**tool_data)
dump_value(value) return_to_llm(value)
def dump_value(value): def return_to_llm(value):
if value is None: if value is None:
return return
if "LLM_OUTPUT" in os.environ:
writer = open(os.environ["LLM_OUTPUT"], "w")
else:
writer = sys.stdout
value_type = type(value).__name__ value_type = type(value).__name__
if value_type in ("str", "int", "float", "bool"): if value_type in ("str", "int", "float", "bool"):
print(value) writer.write(value)
elif value_type == "dict" or value_type == "list": elif value_type == "dict" or value_type == "list":
value_str = json.dumps(value, indent=2) value_str = json.dumps(value, indent=2)
assert value == json.loads(value_str) assert value == json.loads(value_str)
print(value_str) writer.write(value_str)
if __name__ == "__main__": if __name__ == "__main__":
+33 -11
View File
@@ -2,16 +2,16 @@
set -e set -e
main() { main() {
this_file_name=run-tool.sh
parse_argv "$@"
root_dir="$(cd -- "$( dirname -- "${BASH_SOURCE[0]}" )/.." &> /dev/null && pwd)" root_dir="$(cd -- "$( dirname -- "${BASH_SOURCE[0]}" )/.." &> /dev/null && pwd)"
self_name=run-tool.sh
parse_argv "$@"
setup_env setup_env
tool_path="$root_dir/tools/$tool_name.sh" tool_path="$root_dir/tools/$tool_name.sh"
run run
} }
parse_argv() { parse_argv() {
if [[ "$0" == *"$this_file_name" ]]; then if [[ "$0" == *"$self_name" ]]; then
tool_name="$1" tool_name="$1"
tool_data="$2" tool_data="$2"
else else
@@ -24,28 +24,42 @@ parse_argv() {
} }
setup_env() { setup_env() {
load_env "$root_dir/.env"
export LLM_ROOT_DIR="$root_dir" export LLM_ROOT_DIR="$root_dir"
if [[ -f "$LLM_ROOT_DIR/.env" ]]; then
set -o allexport && source "$LLM_ROOT_DIR/.env" && set +o allexport
fi
export LLM_TOOL_NAME="$tool_name" export LLM_TOOL_NAME="$tool_name"
export LLM_TOOL_CACHE_DIR="$LLM_ROOT_DIR/cache/$tool_name" export LLM_TOOL_CACHE_DIR="$LLM_ROOT_DIR/cache/$tool_name"
} }
load_env() {
local env_file="$1" env_vars
if [[ -f "$env_file" ]]; then
while IFS='=' read -r key value; do
if [[ "$key" == $'#'* ]] || [[ -z "$key" ]]; then
continue
fi
if [[ -z "${!key+x}" ]]; then
env_vars="$env_vars $key=$value"
fi
done < "$env_file"
if [[ -n "$env_vars" ]]; then
eval "export $env_vars"
fi
fi
}
run() { run() {
if [[ -z "$tool_data" ]]; then if [[ -z "$tool_data" ]]; then
die "No JSON data" die "No JSON data"
fi fi
_jq=jq
if [[ "$OS" == "Windows_NT" ]]; then if [[ "$OS" == "Windows_NT" ]]; then
_jq="jq -b" set -o igncr
tool_path="$(cygpath -w "$tool_path")" tool_path="$(cygpath -w "$tool_path")"
fi fi
data="$( data="$(
echo "$tool_data" | \ echo "$tool_data" | \
$_jq -r ' jq -r '
to_entries | .[] | to_entries | .[] |
(.key | split("_") | join("-")) as $key | (.key | split("_") | join("-")) as $key |
if .value | type == "array" then if .value | type == "array" then
@@ -62,10 +76,18 @@ run() {
if [[ "$line" == '--'* ]]; then if [[ "$line" == '--'* ]]; then
args+=("$line") args+=("$line")
else else
args+=("$(echo "$line" | $_jq -r '.')") args+=("$(echo "$line" | jq -r '.')")
fi fi
done <<< "$data" done <<< "$data"
no_llm_output=0
if [[ -z "$LLM_OUTPUT" ]]; then
no_llm_output=1
export LLM_OUTPUT="$(mktemp)"
fi
"$tool_path" "${args[@]}" "$tool_path" "${args[@]}"
if [[ "$no_llm_output" -eq 1 ]]; then
cat "$LLM_OUTPUT"
fi
} }
die() { die() {
+10 -5
View File
@@ -12,13 +12,18 @@
* @param {Args} args * @param {Args} args
*/ */
exports.run = function run(args) { exports.run = function run(args) {
for (const [key, value] of Object.entries(args)) { let output = `string: ${args.string}
console.log(`${key}: ${JSON.stringify(value)}`); string_enum: ${args.string_enum}
} string_optional: ${args.string_optional}
boolean: ${args.boolean}
integer: ${args.integer}
number: ${args.number}
array: ${args.array}
array_optional: ${args.array_optional}`;
for (const [key, value] of Object.entries(process.env)) { for (const [key, value] of Object.entries(process.env)) {
if (key.startsWith("LLM_")) { if (key.startsWith("LLM_")) {
console.log(`${key}: ${value}`); output = `${output}\n${key}: ${value}`;
} }
} }
return output;
} }
+14 -6
View File
@@ -2,29 +2,37 @@ import os
from typing import List, Literal, Optional from typing import List, Literal, Optional
def run( def run(
boolean: bool,
string: str, string: str,
string_enum: Literal["foo", "bar"], string_enum: Literal["foo", "bar"],
boolean: bool,
integer: int, integer: int,
number: float, number: float,
array: List[str], array: List[str],
string_optional: Optional[str] = None, string_optional: Optional[str] = None,
array_optional: Optional[List[str]] = None, array_optional: Optional[List[str]] = None,
) -> None: ):
"""Demonstrate how to create a tool using Python and how to use comments. """Demonstrate how to create a tool using Python and how to use comments.
Args: Args:
boolean: Define a required boolean property
string: Define a required string property string: Define a required string property
string_enum: Define a required string property with enum string_enum: Define a required string property with enum
boolean: Define a required boolean property
integer: Define a required integer property integer: Define a required integer property
number: Define a required number property number: Define a required number property
array: Define a required string array property array: Define a required string array property
string_optional: Define a optional string property string_optional: Define a optional string property
array_optional: Define a optional string array property array_optional: Define a optional string array property
""" """
for key, value in locals().items(): output = f"""string: {string}
print(f"{key}: {value}") 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(): for key, value in os.environ.items():
if key.startswith("LLM_"): if key.startswith("LLM_"):
print(f"{key}: {value}") output = f"{output}\n{key}: {value}"
return output
+15 -3
View File
@@ -1,3 +1,6 @@
#!/usr/bin/env bash
set -e
# @describe Demonstrate how to create a tool using Bash and how to use comment tags. # @describe Demonstrate how to create a tool using Bash and how to use comment tags.
# @option --string! Define a required string property # @option --string! Define a required string property
# @option --string-enum![foo|bar] Define a required string property with enum # @option --string-enum![foo|bar] Define a required string property with enum
@@ -9,8 +12,17 @@
# @option --array-optional* Define a optional string array property # @option --array-optional* Define a optional string array property
main() { main() {
( set -o posix ; set ) | grep ^argc_ cat <<EOF >> "$LLM_OUTPUT"
printenv | grep '^LLM_' 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
} }
eval "$(argc --argc-eval "$0" "$@")" eval "$(argc --argc-eval "$0" "$@")"
+10 -3
View File
@@ -1,11 +1,18 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -e set -e
# @describe Runs a shell command. # @describe Runs the shell command.
# @option --command! The command to execute. # @option --command! The command to execute.
main() { main() {
eval "$argc_command" if [ -t 1 ]; then
read -r -p "Are you sure you want to continue? [Y/n] " ans
if [[ "$ans" == "N" || "$ans" == "n" ]]; then
echo "Aborted!"
exit 1
fi
fi
eval "$argc_command" >> "$LLM_OUTPUT"
} }
eval "$(argc --argc-eval "$0" "$@")" eval "$(argc --argc-eval "$0" "$@")"
+1 -1
View File
@@ -5,5 +5,5 @@
* @param {Args} args * @param {Args} args
*/ */
exports.run = function run({ code }) { exports.run = function run({ code }) {
eval(code); return eval(code);
} }
+1 -1
View File
@@ -3,4 +3,4 @@ def run(code: str):
Args: Args:
code: Python code to execute, such as `print("hello world")` code: Python code to execute, such as `print("hello world")`
""" """
exec(code) return exec(code)
+1 -1
View File
@@ -9,7 +9,7 @@ set -e
main() { main() {
path="$FS_BASE_DIR/$argc_path" path="$FS_BASE_DIR/$argc_path"
cat "$path" cat "$path" >> "$LLM_OUTPUT"
} }
eval "$(argc --argc-eval "$0" "$@")" eval "$(argc --argc-eval "$0" "$@")"
+1 -1
View File
@@ -8,7 +8,7 @@ set -e
main() { main() {
path="$FS_BASE_DIR/$argc_path" path="$FS_BASE_DIR/$argc_path"
ls -1 "$path" ls -1 "$path" >> "$LLM_OUTPUT"
} }
eval "$(argc --argc-eval "$0" "$@")" eval "$(argc --argc-eval "$0" "$@")"
+1 -1
View File
@@ -9,7 +9,7 @@ set -e
main() { main() {
path="$FS_BASE_DIR/$argc_path" path="$FS_BASE_DIR/$argc_path"
mkdir -p "$path" mkdir -p "$path"
echo "Directory created: $path" echo "Directory created: $path" >> "$LLM_OUTPUT"
} }
eval "$(argc --argc-eval "$0" "$@")" eval "$(argc --argc-eval "$0" "$@")"
+1 -1
View File
@@ -9,7 +9,7 @@ set -e
main() { main() {
path="$FS_BASE_DIR/$argc_path" path="$FS_BASE_DIR/$argc_path"
rm -rf "$path" rm -rf "$path"
echo "Path removed: $path" echo "Path removed: $path" >> "$LLM_OUTPUT"
} }
eval "$(argc --argc-eval "$0" "$@")" eval "$(argc --argc-eval "$0" "$@")"
+1 -1
View File
@@ -14,7 +14,7 @@ main() {
path="$FS_BASE_DIR/$argc_path" path="$FS_BASE_DIR/$argc_path"
mkdir -p "$(dirname "$path")" mkdir -p "$(dirname "$path")"
printf "%s" "$argc_contents" > "$path" printf "%s" "$argc_contents" > "$path"
echo "The contents written to: $path" echo "The contents written to: $path" >> "$LLM_OUTPUT"
} }
eval "$(argc --argc-eval "$0" "$@")" eval "$(argc --argc-eval "$0" "$@")"
+1 -2
View File
@@ -4,8 +4,7 @@ set -e
# @describe Get the current time. # @describe Get the current time.
main() { main() {
date date >> "$LLM_OUTPUT"
} }
eval "$(argc --argc-eval "$0" "$@")" eval "$(argc --argc-eval "$0" "$@")"
+2 -1
View File
@@ -5,7 +5,8 @@ set -e
# @option --location! The city and optionally the state or country, e.g., "London", "San Francisco, CA". # @option --location! The city and optionally the state or country, e.g., "London", "San Francisco, CA".
main() { main() {
curl -fsSL "https://wttr.in/$(echo "$argc_location" | sed 's/ /+/g')?format=4&M" curl -fsSL "https://wttr.in/$(echo "$argc_location" | sed 's/ /+/g')?format=4&M" \
>> "$LLM_OUTPUT"
} }
eval "$(argc --argc-eval "$0" "$@")" eval "$(argc --argc-eval "$0" "$@")"
+2 -1
View File
@@ -9,7 +9,8 @@ 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. # 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" | \ curl -fsSL "$argc_url" | \
pandoc -f html-native_divs-native_spans -t gfm-raw_html | \ pandoc -f html-native_divs-native_spans -t gfm-raw_html | \
sed -E 's/!\[.*?\]\((data:image\/svg\+xml[^)]+)\)//g' sed -E 's/!\[.*?\]\((data:image\/svg\+xml[^)]+)\)//g' \
>> "$LLM_OUTPUT"
} }
eval "$(argc --argc-eval "$0" "$@")" eval "$(argc --argc-eval "$0" "$@")"
+1 -1
View File
@@ -9,7 +9,7 @@ set -e
main() { main() {
encoded_query="$(jq -nr --arg q "$argc_query" '$q|@uri')" 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" url="http://export.arxiv.org/api/query?search_query=all:$encoded_query&max_results=$ARXIV_MAX_RESULTS"
curl -fsSL "$url" curl -fsSL "$url" >> "$LLM_OUTPUT"
} }
eval "$(argc --argc-eval "$0" "$@")" eval "$(argc --argc-eval "$0" "$@")"
+2 -2
View File
@@ -13,8 +13,8 @@ main() {
url="https://api.bing.microsoft.com/v7.0/search?q=$encoded_query&mkt=en-us&textdecorations=true&textformat=raw&count=$BING_MAX_RESULTS&offset=0" url="https://api.bing.microsoft.com/v7.0/search?q=$encoded_query&mkt=en-us&textdecorations=true&textformat=raw&count=$BING_MAX_RESULTS&offset=0"
curl -fsSL "$url" \ curl -fsSL "$url" \
-H "Ocp-Apim-Subscription-Key: $BING_API_KEY" | \ -H "Ocp-Apim-Subscription-Key: $BING_API_KEY" | \
jq '[.webPages.value[] | {name: .name, url: .url, snippet: .snippet}]' jq '[.webPages.value[] | {name: .name, url: .url, snippet: .snippet}]' \
>> "$LLM_OUTPUT"
} }
eval "$(argc --argc-eval "$0" "$@")" eval "$(argc --argc-eval "$0" "$@")"
+2 -2
View File
@@ -14,8 +14,8 @@ main() {
curl -fsSL "$url" \ curl -fsSL "$url" \
-H "Accept: application/json" \ -H "Accept: application/json" \
-H "X-Subscription-Token: $BRAVE_API_KEY" | \ -H "X-Subscription-Token: $BRAVE_API_KEY" | \
jq '[.web.results[] | {title: .title, url: .url, description: .description}]' jq '[.web.results[] | {title: .title, url: .url, description: .description}]' \
>> "$LLM_OUTPUT"
} }
eval "$(argc --argc-eval "$0" "$@")" eval "$(argc --argc-eval "$0" "$@")"
+1 -1
View File
@@ -9,7 +9,7 @@ set -e
# @option --query! The query to search for. # @option --query! The query to search for.
main() { main() {
ddgr -n $DDG_MAX_RESULTS --json "$argc_query" ddgr -n $DDG_MAX_RESULTS --json "$argc_query" >> "$LLM_OUTPUT"
} }
eval "$(argc --argc-eval "$0" "$@")" eval "$(argc --argc-eval "$0" "$@")"
+2 -3
View File
@@ -23,9 +23,8 @@ main() {
} }
} }
}' | \ }' | \
jq '[.results[] | {title: .title, url: .url, text: .text}]' jq '[.results[] | {title: .title, url: .url, text: .text}]' \
>> "$LLM_OUTPUT"
} }
eval "$(argc --argc-eval "$0" "$@")" eval "$(argc --argc-eval "$0" "$@")"
+2 -2
View File
@@ -13,8 +13,8 @@ main() {
encoded_query="$(jq -nr --arg q "$argc_query" '$q|@uri')" encoded_query="$(jq -nr --arg q "$argc_query" '$q|@uri')"
url="https://www.googleapis.com/customsearch/v1?key=$GOOGLE_API_KEY&cx=$GOOGLE_CSE_ID&q=$encoded_query" url="https://www.googleapis.com/customsearch/v1?key=$GOOGLE_API_KEY&cx=$GOOGLE_CSE_ID&q=$encoded_query"
curl -fsSL "$url" | \ curl -fsSL "$url" | \
jq '[.items[:'"$GOOGLE_MAX_RESULTS"'] | .[] | {title: .title, link: .link, snippet: .snippet}]' jq '[.items[:'"$GOOGLE_MAX_RESULTS"'] | .[] | {title: .title, link: .link, snippet: .snippet}]' \
>> "$LLM_OUTPUT"
} }
eval "$(argc --argc-eval "$0" "$@")" eval "$(argc --argc-eval "$0" "$@")"
+2 -2
View File
@@ -12,9 +12,9 @@ main() {
encoded_query="$(jq -nr --arg q "$argc_query" '$q|@uri')" encoded_query="$(jq -nr --arg q "$argc_query" '$q|@uri')"
url="$SEARXNG_API_BASE/search?q=$encoded_query&categories=general&language=en-US&format=json" url="$SEARXNG_API_BASE/search?q=$encoded_query&categories=general&language=en-US&format=json"
curl -fsSL "$url" | \ curl -fsSL "$url" | \
jq '[.results[:'"$SEARXNG_MAX_RESULTS"'] | .[] | {url: .url, title: .title, content: .content}]' jq '[.results[:'"$SEARXNG_MAX_RESULTS"'] | .[] | {url: .url, title: .title, content: .content}]' \
>> "$LLM_OUTPUT"
} }
eval "$(argc --argc-eval "$0" "$@")" eval "$(argc --argc-eval "$0" "$@")"
+2 -2
View File
@@ -18,8 +18,8 @@ main() {
"search_depth": "advanced", "search_depth": "advanced",
"max_results": "'"$TAVILY_MAX_RESULTS"'" "max_results": "'"$TAVILY_MAX_RESULTS"'"
}' | \ }' | \
jq '[.results[] | {title: .title, url: .url, content: .content}]' jq '[.results[] | {title: .title, url: .url, content: .content}]' \
>> "$LLM_OUTPUT"
} }
eval "$(argc --argc-eval "$0" "$@")" eval "$(argc --argc-eval "$0" "$@")"
+1 -1
View File
@@ -20,7 +20,7 @@ main() {
echo '{ echo '{
"link": "https://en.wikipedia.org/wiki/'"$title"'", "link": "https://en.wikipedia.org/wiki/'"$title"'",
"summary": "'"$summary"'" "summary": "'"$summary"'"
}' }' >> "$LLM_OUTPUT"
} }
eval "$(argc --argc-eval "$0" "$@")" eval "$(argc --argc-eval "$0" "$@")"
+2 -1
View File
@@ -10,7 +10,8 @@ set -e
main() { main() {
encoded_query="$(jq -nr --arg q "$argc_query" '$q|@uri')" 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" 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(. != "")]}]' curl -fsSL "$url" | jq '[.queryresult | .pods[] | {title:.title, values:[.subpods[].plaintext | select(. != "")]}]' \
>> "$LLM_OUTPUT"
} }
eval "$(argc --argc-eval "$0" "$@")" eval "$(argc --argc-eval "$0" "$@")"
+1 -1
View File
@@ -23,7 +23,7 @@ $argc_body" | \
--mail-from "$EMAIL_SMTP_USER" \ --mail-from "$EMAIL_SMTP_USER" \
--mail-rcpt "$argc_recipient" \ --mail-rcpt "$argc_recipient" \
--upload-file - --upload-file -
echo "Email sent successfully" echo "Email sent successfully" >> "$LLM_OUTPUT"
} }
eval "$(argc --argc-eval "$0" "$@")" eval "$(argc --argc-eval "$0" "$@")"