aia 1.0.0.pre.beta → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.version +1 -1
- data/CHANGELOG.md +89 -0
- data/COMMITS.md +192 -11
- data/README.md +327 -110
- data/docs/cli-reference.md +93 -10
- data/docs/configuration.md +29 -36
- data/docs/contributing.md +2 -2
- data/docs/directives-reference.md +49 -27
- data/docs/examples/index.md +2 -2
- data/docs/examples/mcp/index.md +93 -97
- data/docs/examples/prompts/automation/index.md +3 -2
- data/docs/examples/tools/index.md +17 -27
- data/docs/faq.md +9 -12
- data/docs/guides/basic-usage.md +4 -4
- data/docs/guides/chat.md +39 -34
- data/docs/guides/tools.md +4 -4
- data/docs/index.md +36 -62
- data/docs/installation.md +1 -1
- data/docs/mcp-integration.md +75 -139
- data/docs/prompt_management.md +88 -1
- data/docs/security.md +79 -81
- data/docs/tools-and-mcp-examples.md +8 -6
- data/docs/workflows-and-pipelines.md +2 -6
- data/examples/.gitignore +1 -0
- data/examples/README.md +41 -0
- data/examples/run_all.sh +261 -0
- data/lib/aia/adapter/chat_execution.rb +9 -7
- data/lib/aia/adapter/mcp_connector.rb +0 -29
- data/lib/aia/adapter/modality_handlers.rb +23 -15
- data/lib/aia/adapter/tool_filter.rb +21 -0
- data/lib/aia/adapter/tool_loader.rb +1 -9
- data/lib/aia/chat_loop.rb +244 -0
- data/lib/aia/chat_processor_service.rb +6 -3
- data/lib/aia/config/cli_parser.rb +56 -18
- data/lib/aia/config/defaults.yml +17 -2
- data/lib/aia/config/validator.rb +52 -11
- data/lib/aia/config.rb +29 -3
- data/lib/aia/directive.rb +29 -0
- data/lib/aia/directives/configuration_directives.rb +2 -1
- data/lib/aia/directives/execution_directives.rb +1 -1
- data/lib/aia/directives/model_directives.rb +28 -27
- data/lib/aia/directives/web_and_file_directives.rb +78 -40
- data/lib/aia/errors.rb +20 -1
- data/lib/aia/fzf.rb +8 -7
- data/lib/aia/input_collector.rb +24 -0
- data/lib/aia/prompt_handler.rb +36 -8
- data/lib/aia/prompt_pipeline.rb +183 -0
- data/lib/aia/session.rb +22 -372
- data/lib/aia/skill_utils.rb +61 -0
- data/lib/aia/ui_presenter.rb +8 -0
- data/lib/aia.rb +4 -0
- metadata +19 -45
data/examples/README.md
CHANGED
|
@@ -185,11 +185,51 @@ Docs: [Executable Prompts](https://madbomber.github.io/aia/guides/executable-pro
|
|
|
185
185
|
|
|
186
186
|
Docs: [Chat Guide](https://madbomber.github.io/aia/guides/chat/), [Directives Reference](https://madbomber.github.io/aia/directives-reference/), [Workflows and Pipelines](https://madbomber.github.io/aia/workflows-and-pipelines/)
|
|
187
187
|
|
|
188
|
+
## Running All Demos
|
|
189
|
+
|
|
190
|
+
`run_all.sh` runs all non-interactive demo scripts in sequence and captures the combined output. It serves as a structural integration test — since LLM responses are non-deterministic, exact diffs between runs won't match, but you can spot missing sections, crashes, or changed command output.
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
cd examples
|
|
194
|
+
|
|
195
|
+
# Run all demos and save output to a timestamped log
|
|
196
|
+
bash run_all.sh
|
|
197
|
+
|
|
198
|
+
# Print to terminal only (no log file)
|
|
199
|
+
bash run_all.sh --no-save
|
|
200
|
+
|
|
201
|
+
# Save to your own file with tee
|
|
202
|
+
bash run_all.sh --no-save 2>&1 | tee my_run.log
|
|
203
|
+
|
|
204
|
+
# Show help
|
|
205
|
+
bash run_all.sh --help
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Output logs are saved to `examples/output/run_YYYYMMDD_HHMMSS.log`. Compare runs with:
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
diff output/run_PREV.log output/run_LATEST.log
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
**What it runs:** Scripts 01-14, 16-19, and 21 (18 scripts total).
|
|
215
|
+
|
|
216
|
+
**What it skips:**
|
|
217
|
+
|
|
218
|
+
| Script | Reason |
|
|
219
|
+
|--------|--------|
|
|
220
|
+
| `00_setup_aia.sh` | Run manually first (pulls models, writes config) |
|
|
221
|
+
| `15_parameters.sh` | Part 2 prompts interactively for a required parameter |
|
|
222
|
+
| `20_mcp_servers.sh` | Requires Node.js/npx + MCP filesystem server |
|
|
223
|
+
| `22_chat_mode.sh` | Interactive chat session (uses `expect`) |
|
|
224
|
+
|
|
225
|
+
The output includes a banner with version info, per-script pass/fail status, and a summary with counts.
|
|
226
|
+
|
|
188
227
|
## Directory Structure
|
|
189
228
|
|
|
190
229
|
```
|
|
191
230
|
examples/
|
|
192
231
|
common.sh # Shared setup sourced by all demos
|
|
232
|
+
run_all.sh # Batch runner for non-interactive demos
|
|
193
233
|
aia_config.yml # Generated by 00_setup_aia.sh
|
|
194
234
|
aia_config_with_mcp.yml # Config with MCP server (demo 20)
|
|
195
235
|
prompts_dir/ # All demo prompt files
|
|
@@ -199,6 +239,7 @@ examples/
|
|
|
199
239
|
directives/ # Custom directive files (demo 16)
|
|
200
240
|
tools/ # Local tool files (demo 19)
|
|
201
241
|
mcp/ # MCP server configs (demo 20)
|
|
242
|
+
output/ # Timestamped run logs (git-ignored)
|
|
202
243
|
```
|
|
203
244
|
|
|
204
245
|
## Notes
|
data/examples/run_all.sh
ADDED
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# examples/run_all.sh
|
|
3
|
+
#
|
|
4
|
+
# Runs all example demo scripts in order and captures output.
|
|
5
|
+
#
|
|
6
|
+
# The output is saved to a timestamped file for comparison against
|
|
7
|
+
# future runs — a super-meta integration test. Since LLM responses
|
|
8
|
+
# are non-deterministic, exact diffs won't match; look for structural
|
|
9
|
+
# differences (missing sections, crashes, changed command output).
|
|
10
|
+
#
|
|
11
|
+
# What it skips:
|
|
12
|
+
# - 00_setup_aia.sh — run manually first (pulls models, writes config)
|
|
13
|
+
# - 15_parameters.sh — Part 2 prompts interactively for a required param
|
|
14
|
+
# - 20_mcp_servers.sh — requires Node.js/npx + MCP filesystem server
|
|
15
|
+
# - 22_chat_mode.sh — interactive chat (Parts 1-4 use expect; Part 5
|
|
16
|
+
# opens a live session)
|
|
17
|
+
#
|
|
18
|
+
# Prerequisites:
|
|
19
|
+
# - Run 00_setup_aia.sh first
|
|
20
|
+
# - Ollama running with qwen3 model available
|
|
21
|
+
#
|
|
22
|
+
# Usage:
|
|
23
|
+
# cd examples
|
|
24
|
+
# bash run_all.sh # run and save output
|
|
25
|
+
# bash run_all.sh --no-save # run without saving (just print)
|
|
26
|
+
# diff output/run_PREV.log output/run_LATEST.log # compare runs
|
|
27
|
+
#
|
|
28
|
+
# Exit codes:
|
|
29
|
+
# 0 — all scripts completed (some may have non-fatal warnings)
|
|
30
|
+
# 1 — setup not done or a script failed fatally
|
|
31
|
+
|
|
32
|
+
set -uo pipefail
|
|
33
|
+
|
|
34
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
35
|
+
cd "${SCRIPT_DIR}"
|
|
36
|
+
|
|
37
|
+
# --- Usage ---
|
|
38
|
+
|
|
39
|
+
usage() {
|
|
40
|
+
cat <<'USAGE'
|
|
41
|
+
Usage: bash run_all.sh [OPTIONS]
|
|
42
|
+
|
|
43
|
+
Run all non-interactive AIA example scripts and capture output.
|
|
44
|
+
|
|
45
|
+
Options:
|
|
46
|
+
-h, --help Show this help message and exit
|
|
47
|
+
--no-save Print output to the terminal only (do not save a log file)
|
|
48
|
+
|
|
49
|
+
By default the output is saved to examples/output/run_YYYYMMDD_HHMMSS.log.
|
|
50
|
+
Since LLM responses are non-deterministic, exact diffs between runs won't
|
|
51
|
+
match; look for structural differences (missing sections, crashes, changed
|
|
52
|
+
command output).
|
|
53
|
+
|
|
54
|
+
Saving output with tee:
|
|
55
|
+
bash run_all.sh --no-save 2>&1 | tee my_run.log
|
|
56
|
+
|
|
57
|
+
Use --no-save so the script does not write its own log file, then pipe
|
|
58
|
+
through tee to send output to both the terminal and your chosen file.
|
|
59
|
+
|
|
60
|
+
Comparing runs:
|
|
61
|
+
diff output/run_PREV.log output/run_LATEST.log
|
|
62
|
+
|
|
63
|
+
Skipped scripts (require manual or interactive setup):
|
|
64
|
+
00_setup_aia.sh — run manually first (pulls models, writes config)
|
|
65
|
+
15_parameters.sh — Part 2 prompts interactively for a required param
|
|
66
|
+
20_mcp_servers.sh — requires Node.js/npx + MCP filesystem server
|
|
67
|
+
22_chat_mode.sh — interactive chat session
|
|
68
|
+
|
|
69
|
+
Prerequisites:
|
|
70
|
+
1. Run 00_setup_aia.sh first
|
|
71
|
+
2. Ollama running with the qwen3 model available
|
|
72
|
+
|
|
73
|
+
Exit codes:
|
|
74
|
+
0 All scripts completed (some may have non-fatal warnings)
|
|
75
|
+
1 Setup not done or a script failed fatally
|
|
76
|
+
USAGE
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
# --- Parse flags ---
|
|
80
|
+
|
|
81
|
+
SAVE_OUTPUT=true
|
|
82
|
+
case "${1:-}" in
|
|
83
|
+
-h|--help)
|
|
84
|
+
usage
|
|
85
|
+
exit 0
|
|
86
|
+
;;
|
|
87
|
+
--no-save)
|
|
88
|
+
SAVE_OUTPUT=false
|
|
89
|
+
;;
|
|
90
|
+
esac
|
|
91
|
+
|
|
92
|
+
# --- Pre-flight checks ---
|
|
93
|
+
|
|
94
|
+
if [[ ! -f "aia_config.yml" ]]; then
|
|
95
|
+
echo "ERROR: aia_config.yml not found."
|
|
96
|
+
echo " Run 00_setup_aia.sh first."
|
|
97
|
+
exit 1
|
|
98
|
+
fi
|
|
99
|
+
|
|
100
|
+
if ! command -v aia &>/dev/null; then
|
|
101
|
+
echo "ERROR: aia is not installed."
|
|
102
|
+
exit 1
|
|
103
|
+
fi
|
|
104
|
+
|
|
105
|
+
# --- Scripts to run ---
|
|
106
|
+
# Order matters: numbered scripts build on each other conceptually.
|
|
107
|
+
# Scripts are listed explicitly so we can annotate skips.
|
|
108
|
+
|
|
109
|
+
SCRIPTS=(
|
|
110
|
+
01_basic_usage.sh
|
|
111
|
+
02_frontmatter.sh
|
|
112
|
+
03_shell_integration.sh
|
|
113
|
+
04_erb_templating.sh
|
|
114
|
+
05_shell_then_erb.sh
|
|
115
|
+
06_prompt_chaining.sh
|
|
116
|
+
07_pipeline.sh
|
|
117
|
+
08_context_files.sh
|
|
118
|
+
09_roles.sh
|
|
119
|
+
10_stdin_piping.sh
|
|
120
|
+
11_multi_model.sh
|
|
121
|
+
12_token_usage.sh
|
|
122
|
+
13_cost_tracking.sh
|
|
123
|
+
14_output_file.sh
|
|
124
|
+
# 15_parameters.sh — skipped: Part 2 blocks on interactive input
|
|
125
|
+
16_directives.sh
|
|
126
|
+
17_require_and_conditionals.sh
|
|
127
|
+
18_tools.sh
|
|
128
|
+
19_local_tools.sh
|
|
129
|
+
# 20_mcp_servers.sh — skipped: requires npx + MCP server
|
|
130
|
+
21_executable_prompts.sh
|
|
131
|
+
# 22_chat_mode.sh — skipped: interactive chat session
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
SKIPPED=(
|
|
135
|
+
"15_parameters.sh (interactive parameter input)"
|
|
136
|
+
"20_mcp_servers.sh (requires Node.js/npx + MCP server)"
|
|
137
|
+
"22_chat_mode.sh (interactive chat session)"
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
# --- Set up output ---
|
|
141
|
+
|
|
142
|
+
TIMESTAMP="$(date +%Y%m%d_%H%M%S)"
|
|
143
|
+
OUTPUT_DIR="${SCRIPT_DIR}/output"
|
|
144
|
+
OUTPUT_FILE="${OUTPUT_DIR}/run_${TIMESTAMP}.log"
|
|
145
|
+
|
|
146
|
+
if [[ "${SAVE_OUTPUT}" == true ]]; then
|
|
147
|
+
mkdir -p "${OUTPUT_DIR}"
|
|
148
|
+
fi
|
|
149
|
+
|
|
150
|
+
# --- Banner ---
|
|
151
|
+
|
|
152
|
+
banner() {
|
|
153
|
+
cat <<EOF
|
|
154
|
+
================================================================================
|
|
155
|
+
AIA Examples — Full Run
|
|
156
|
+
Date: $(date '+%Y-%m-%d %H:%M:%S')
|
|
157
|
+
AIA: $(aia --version 2>/dev/null || echo "unknown")
|
|
158
|
+
Ruby: $(ruby --version 2>/dev/null | head -1)
|
|
159
|
+
Model: $(grep 'name:' aia_config.yml | head -1 | sed 's/.*name: *//')
|
|
160
|
+
================================================================================
|
|
161
|
+
|
|
162
|
+
Skipped scripts:
|
|
163
|
+
$(printf ' - %s\n' "${SKIPPED[@]}")
|
|
164
|
+
|
|
165
|
+
Running ${#SCRIPTS[@]} scripts ...
|
|
166
|
+
|
|
167
|
+
EOF
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
# --- Run a single script ---
|
|
171
|
+
|
|
172
|
+
run_script() {
|
|
173
|
+
local script="$1"
|
|
174
|
+
local index="$2"
|
|
175
|
+
local total="$3"
|
|
176
|
+
local status
|
|
177
|
+
|
|
178
|
+
echo "──────────────────────────────────────────────────────────────"
|
|
179
|
+
echo " [${index}/${total}] ${script}"
|
|
180
|
+
echo "──────────────────────────────────────────────────────────────"
|
|
181
|
+
echo
|
|
182
|
+
|
|
183
|
+
if [[ ! -f "${script}" ]]; then
|
|
184
|
+
echo " SKIP: file not found"
|
|
185
|
+
echo
|
|
186
|
+
return 0
|
|
187
|
+
fi
|
|
188
|
+
|
|
189
|
+
bash "${script}" 2>&1
|
|
190
|
+
status=$?
|
|
191
|
+
|
|
192
|
+
echo
|
|
193
|
+
if [[ ${status} -eq 0 ]]; then
|
|
194
|
+
echo " ✓ ${script} completed (exit ${status})"
|
|
195
|
+
else
|
|
196
|
+
echo " ✗ ${script} FAILED (exit ${status})"
|
|
197
|
+
fi
|
|
198
|
+
echo
|
|
199
|
+
|
|
200
|
+
return ${status}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
# --- Main ---
|
|
204
|
+
|
|
205
|
+
main() {
|
|
206
|
+
banner
|
|
207
|
+
|
|
208
|
+
local total=${#SCRIPTS[@]}
|
|
209
|
+
local passed=0
|
|
210
|
+
local failed=0
|
|
211
|
+
local failures=()
|
|
212
|
+
|
|
213
|
+
for i in "${!SCRIPTS[@]}"; do
|
|
214
|
+
local script="${SCRIPTS[$i]}"
|
|
215
|
+
local index=$((i + 1))
|
|
216
|
+
|
|
217
|
+
if run_script "${script}" "${index}" "${total}"; then
|
|
218
|
+
((passed++))
|
|
219
|
+
else
|
|
220
|
+
((failed++))
|
|
221
|
+
failures+=("${script}")
|
|
222
|
+
fi
|
|
223
|
+
done
|
|
224
|
+
|
|
225
|
+
echo "================================================================================"
|
|
226
|
+
echo " Summary"
|
|
227
|
+
echo "================================================================================"
|
|
228
|
+
echo
|
|
229
|
+
echo " Total: ${total}"
|
|
230
|
+
echo " Passed: ${passed}"
|
|
231
|
+
echo " Failed: ${failed}"
|
|
232
|
+
echo " Skipped: ${#SKIPPED[@]}"
|
|
233
|
+
echo
|
|
234
|
+
|
|
235
|
+
if [[ ${failed} -gt 0 ]]; then
|
|
236
|
+
echo " Failed scripts:"
|
|
237
|
+
printf ' - %s\n' "${failures[@]}"
|
|
238
|
+
echo
|
|
239
|
+
fi
|
|
240
|
+
|
|
241
|
+
if [[ "${SAVE_OUTPUT}" == true ]]; then
|
|
242
|
+
echo " Output saved to: ${OUTPUT_FILE}"
|
|
243
|
+
echo
|
|
244
|
+
fi
|
|
245
|
+
|
|
246
|
+
echo " To compare against a future run:"
|
|
247
|
+
echo " diff output/run_PREV.log output/run_LATEST.log"
|
|
248
|
+
echo
|
|
249
|
+
echo "================================================================================"
|
|
250
|
+
|
|
251
|
+
return ${failed}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
# --- Execute ---
|
|
255
|
+
|
|
256
|
+
if [[ "${SAVE_OUTPUT}" == true ]]; then
|
|
257
|
+
main 2>&1 | tee "${OUTPUT_FILE}"
|
|
258
|
+
exit ${PIPESTATUS[0]}
|
|
259
|
+
else
|
|
260
|
+
main
|
|
261
|
+
fi
|
|
@@ -117,14 +117,16 @@ module AIA
|
|
|
117
117
|
|
|
118
118
|
# Report failed models but continue with valid ones
|
|
119
119
|
unless failed_models.empty?
|
|
120
|
-
|
|
121
|
-
failed_models.each { |failure|
|
|
120
|
+
warn "\nFailed to initialize the following models:"
|
|
121
|
+
failed_models.each { |failure| warn " - #{failure}" }
|
|
122
|
+
logger = LoggerManager.aia_logger
|
|
123
|
+
failed_models.each { |failure| logger.error("Model initialization failed: #{failure}") }
|
|
122
124
|
end
|
|
123
125
|
|
|
124
126
|
# If no models initialized successfully, exit
|
|
125
127
|
if valid_chats.empty?
|
|
126
|
-
|
|
127
|
-
|
|
128
|
+
warn "\nNo valid models could be initialized. Exiting."
|
|
129
|
+
warn "\nAvailable models can be listed with: bin/aia --help models"
|
|
128
130
|
exit 1
|
|
129
131
|
end
|
|
130
132
|
|
|
@@ -135,8 +137,7 @@ module AIA
|
|
|
135
137
|
|
|
136
138
|
# Report successful models
|
|
137
139
|
if failed_models.any?
|
|
138
|
-
|
|
139
|
-
puts
|
|
140
|
+
warn "\nSuccessfully initialized: #{@models.join(', ')}"
|
|
140
141
|
end
|
|
141
142
|
|
|
142
143
|
# Use the first chat to determine tool support (assuming all models have similar tool support)
|
|
@@ -222,7 +223,8 @@ module AIA
|
|
|
222
223
|
mcp_connector = McpConnector.new
|
|
223
224
|
tool_loader = ToolLoader.new(mcp_connector)
|
|
224
225
|
|
|
225
|
-
@tools = tool_loader.
|
|
226
|
+
@tools = tool_loader.load_tools
|
|
227
|
+
ToolFilter.detect_conflicts
|
|
226
228
|
@tools = ToolFilter.filter_allowed(@tools)
|
|
227
229
|
@tools = ToolFilter.filter_rejected(@tools)
|
|
228
230
|
@tools = ToolFilter.drop_duplicates(@tools)
|
|
@@ -17,35 +17,6 @@ module AIA
|
|
|
17
17
|
return
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
logger.debug("Starting MCP connection via RubyLLM::MCP.establish_connection")
|
|
21
|
-
LoggerManager.configure_mcp_logger
|
|
22
|
-
|
|
23
|
-
start_time = Time.now
|
|
24
|
-
RubyLLM::MCP.establish_connection
|
|
25
|
-
elapsed = Time.now - start_time
|
|
26
|
-
|
|
27
|
-
tool_count = RubyLLM::MCP.tools.size
|
|
28
|
-
tools.concat(RubyLLM::MCP.tools)
|
|
29
|
-
|
|
30
|
-
logger.info("MCP connection established", elapsed_seconds: elapsed.round(2), tool_count: tool_count)
|
|
31
|
-
rescue StandardError => e
|
|
32
|
-
logger.error("Failed to connect MCP clients", error_class: e.class.name, error_message: e.message)
|
|
33
|
-
logger.debug("MCP connection error backtrace", backtrace: e.backtrace&.first(5))
|
|
34
|
-
warn "Warning: Failed to connect MCP clients: #{e.message}"
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
# =========================================================================
|
|
38
|
-
# SimpleFlow-based Parallel MCP Connection
|
|
39
|
-
# =========================================================================
|
|
40
|
-
# Uses fiber-based concurrency to connect to all MCP servers in parallel.
|
|
41
|
-
# This reduces total connection time from sum(timeouts) to max(timeouts).
|
|
42
|
-
|
|
43
|
-
def support_mcp_with_simple_flow(tools)
|
|
44
|
-
if AIA.config.flags.no_mcp
|
|
45
|
-
logger.debug("MCP processing bypassed via --no-mcp flag")
|
|
46
|
-
return
|
|
47
|
-
end
|
|
48
|
-
|
|
49
20
|
if AIA.config.mcp_servers.nil? || AIA.config.mcp_servers.empty?
|
|
50
21
|
logger.debug("No MCP servers configured, skipping MCP setup")
|
|
51
22
|
return
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# lib/aia/adapter/modality_handlers.rb
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
|
+
require 'tempfile'
|
|
5
|
+
|
|
4
6
|
module AIA
|
|
5
7
|
module Adapter
|
|
6
8
|
module ModalityHandlers
|
|
@@ -11,18 +13,21 @@ module AIA
|
|
|
11
13
|
end
|
|
12
14
|
|
|
13
15
|
def speak(_text)
|
|
14
|
-
output_file = "#{Time.now.to_i}.mp3"
|
|
15
|
-
|
|
16
16
|
# NOTE: RubyLLM doesn't have a direct text-to-speech feature
|
|
17
17
|
# This is a placeholder for a custom implementation or external service
|
|
18
|
+
tmpfile = Tempfile.new(['aia-tts-', '.mp3'])
|
|
18
19
|
begin
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
tmpfile.write('Mock TTS audio content')
|
|
21
|
+
tmpfile.close
|
|
22
|
+
speak_cmd = AIA.config.audio.speak_command
|
|
23
|
+
if system('which', speak_cmd, out: File::NULL, err: File::NULL)
|
|
24
|
+
system(speak_cmd, tmpfile.path)
|
|
22
25
|
end
|
|
23
|
-
"Audio generated
|
|
26
|
+
"Audio generated successfully"
|
|
24
27
|
rescue StandardError => e
|
|
25
28
|
"Error generating audio: #{e.message}"
|
|
29
|
+
ensure
|
|
30
|
+
tmpfile.unlink
|
|
26
31
|
end
|
|
27
32
|
end
|
|
28
33
|
|
|
@@ -55,8 +60,7 @@ module AIA
|
|
|
55
60
|
|
|
56
61
|
# Return the full response object to preserve token information
|
|
57
62
|
response
|
|
58
|
-
rescue
|
|
59
|
-
# Catch ALL exceptions including LoadError, ScriptError, etc.
|
|
63
|
+
rescue StandardError => e
|
|
60
64
|
# Tool crashes should not crash AIA - log and continue gracefully
|
|
61
65
|
handle_tool_crash(chat_instance, e)
|
|
62
66
|
end
|
|
@@ -114,18 +118,22 @@ module AIA
|
|
|
114
118
|
|
|
115
119
|
def text_to_audio_single(prompt, model_name)
|
|
116
120
|
text_prompt = extract_text_prompt(prompt)
|
|
117
|
-
output_file = "#{Time.now.to_i}.mp3"
|
|
118
121
|
|
|
122
|
+
# NOTE: RubyLLM doesn't have a direct TTS feature
|
|
123
|
+
# TODO: This is a placeholder for a custom implementation
|
|
124
|
+
tmpfile = Tempfile.new(['aia-tts-', '.mp3'])
|
|
119
125
|
begin
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
if
|
|
124
|
-
system(
|
|
126
|
+
tmpfile.write(text_prompt)
|
|
127
|
+
tmpfile.close
|
|
128
|
+
speak_cmd = AIA.config.audio.speak_command
|
|
129
|
+
if system('which', speak_cmd, out: File::NULL, err: File::NULL)
|
|
130
|
+
system(speak_cmd, tmpfile.path)
|
|
125
131
|
end
|
|
126
|
-
"Audio generated
|
|
132
|
+
"Audio generated successfully"
|
|
127
133
|
rescue StandardError => e
|
|
128
134
|
"Error generating audio: #{e.message}"
|
|
135
|
+
ensure
|
|
136
|
+
tmpfile.unlink
|
|
129
137
|
end
|
|
130
138
|
end
|
|
131
139
|
|
|
@@ -30,6 +30,27 @@ module AIA
|
|
|
30
30
|
end
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
+
def self.detect_conflicts
|
|
34
|
+
allowed = AIA.config.tools.allowed
|
|
35
|
+
rejected = AIA.config.tools.rejected
|
|
36
|
+
return [] if allowed.nil? || allowed.empty? || rejected.nil? || rejected.empty?
|
|
37
|
+
|
|
38
|
+
allowed_list = Array(allowed).map(&:strip)
|
|
39
|
+
rejected_list = Array(rejected).map(&:strip)
|
|
40
|
+
|
|
41
|
+
conflicts = allowed_list & rejected_list
|
|
42
|
+
return [] if conflicts.empty?
|
|
43
|
+
|
|
44
|
+
logger = LoggerManager.aia_logger
|
|
45
|
+
conflicts.each do |pattern|
|
|
46
|
+
msg = "Tool pattern '#{pattern}' appears in both --allowed-tools and --rejected-tools. Rejected takes precedence."
|
|
47
|
+
logger.warn(msg)
|
|
48
|
+
warn "WARNING: #{msg}"
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
conflicts
|
|
52
|
+
end
|
|
53
|
+
|
|
33
54
|
def self.drop_duplicates(tools)
|
|
34
55
|
seen_names = Set.new
|
|
35
56
|
original_size = tools.size
|
|
@@ -8,15 +8,7 @@ module AIA
|
|
|
8
8
|
@mcp_connector = mcp_connector
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
def
|
|
12
|
-
tools = []
|
|
13
|
-
|
|
14
|
-
tools += scan_local_tools
|
|
15
|
-
@mcp_connector.support_mcp_with_simple_flow(tools)
|
|
16
|
-
tools
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def load_tools_legacy
|
|
11
|
+
def load_tools
|
|
20
12
|
tools = []
|
|
21
13
|
|
|
22
14
|
tools += scan_local_tools
|