@zachjxyz/moxie 0.4.4 → 0.4.6
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.
- package/bin/moxie +6 -1
- package/lib/agents.sh +103 -0
- package/lib/gateway-models.mjs +84 -0
- package/lib/phases.sh +114 -4
- package/package.json +1 -1
package/bin/moxie
CHANGED
|
@@ -12,11 +12,12 @@
|
|
|
12
12
|
# moxie status
|
|
13
13
|
# moxie cost
|
|
14
14
|
# moxie logs [phase]
|
|
15
|
+
# moxie models [--filter <search>]
|
|
15
16
|
# moxie agents
|
|
16
17
|
|
|
17
18
|
set -euo pipefail
|
|
18
19
|
|
|
19
|
-
MOXIE_VERSION="0.4.
|
|
20
|
+
MOXIE_VERSION="0.4.6"
|
|
20
21
|
# Resolve symlinks (npm installs bin as a symlink)
|
|
21
22
|
_self="$0"
|
|
22
23
|
while [ -L "$_self" ]; do
|
|
@@ -48,6 +49,7 @@ case "$COMMAND" in
|
|
|
48
49
|
status) cmd_status "$@" ;;
|
|
49
50
|
cost) cmd_cost "$@" ;;
|
|
50
51
|
logs) cmd_logs "$@" ;;
|
|
52
|
+
models) cmd_models "$@" ;;
|
|
51
53
|
agents) cmd_agents "$@" ;;
|
|
52
54
|
doctor) cmd_doctor "$@" ;;
|
|
53
55
|
version) echo "moxie $MOXIE_VERSION" ;;
|
|
@@ -63,6 +65,7 @@ Commands:
|
|
|
63
65
|
status Show phase progress, quorum state, and running status
|
|
64
66
|
cost Token usage breakdown by phase and agent
|
|
65
67
|
logs Tail or view logs for a phase
|
|
68
|
+
models List available AI Gateway models
|
|
66
69
|
agents List configured agents
|
|
67
70
|
doctor Check agent CLIs, auth, and project health
|
|
68
71
|
version Print version
|
|
@@ -80,6 +83,8 @@ Usage:
|
|
|
80
83
|
moxie run --dry-run Trace without spawning agents
|
|
81
84
|
moxie status Show progress and quorum
|
|
82
85
|
moxie cost Show token usage summary
|
|
86
|
+
moxie models List all AI Gateway models
|
|
87
|
+
moxie models -f anthropic Filter models by provider/name
|
|
83
88
|
moxie doctor Check agents and dependencies
|
|
84
89
|
|
|
85
90
|
Pipeline: rfc → audit → fix → plan → build
|
package/lib/agents.sh
CHANGED
|
@@ -554,6 +554,109 @@ cmd_agents() {
|
|
|
554
554
|
done
|
|
555
555
|
}
|
|
556
556
|
|
|
557
|
+
# ---- List available gateway models ----
|
|
558
|
+
|
|
559
|
+
cmd_models() {
|
|
560
|
+
local filter=""
|
|
561
|
+
while [ $# -gt 0 ]; do
|
|
562
|
+
case "$1" in
|
|
563
|
+
--filter|-f) filter="$2"; shift 2 ;;
|
|
564
|
+
--help|-h)
|
|
565
|
+
cat <<'EOF'
|
|
566
|
+
Usage: moxie models [--filter <search>]
|
|
567
|
+
|
|
568
|
+
List models available through your Vercel AI Gateway.
|
|
569
|
+
Requires a stored gateway API key (run 'moxie init' to set one up).
|
|
570
|
+
|
|
571
|
+
Options:
|
|
572
|
+
--filter, -f <search> Filter models by provider or name (e.g. "anthropic", "gpt")
|
|
573
|
+
|
|
574
|
+
Examples:
|
|
575
|
+
moxie models List all available models
|
|
576
|
+
moxie models -f anthropic Show only Anthropic models
|
|
577
|
+
moxie models -f gemini Search for Gemini models
|
|
578
|
+
EOF
|
|
579
|
+
return 0
|
|
580
|
+
;;
|
|
581
|
+
*) filter="$1"; shift ;;
|
|
582
|
+
esac
|
|
583
|
+
done
|
|
584
|
+
|
|
585
|
+
if ! command -v node &>/dev/null; then
|
|
586
|
+
echo "ERROR: node not found on PATH. Required for gateway API calls." >&2
|
|
587
|
+
return 1
|
|
588
|
+
fi
|
|
589
|
+
|
|
590
|
+
if ! gateway_has_key "vercel-ai-gateway"; then
|
|
591
|
+
echo "ERROR: No AI Gateway API key configured." >&2
|
|
592
|
+
echo "Run 'moxie init' to set one up, or store a key with:" >&2
|
|
593
|
+
echo " moxie doctor (will prompt for key setup)" >&2
|
|
594
|
+
return 1
|
|
595
|
+
fi
|
|
596
|
+
|
|
597
|
+
local api_key
|
|
598
|
+
api_key=$(gateway_get_key "vercel-ai-gateway") || {
|
|
599
|
+
echo "ERROR: Failed to retrieve gateway API key." >&2
|
|
600
|
+
return 1
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
local endpoint="https://ai-gateway.vercel.sh"
|
|
604
|
+
if [ -f "${MOXIE_CONFIG:-}" ]; then
|
|
605
|
+
local cfg_endpoint
|
|
606
|
+
cfg_endpoint=$(toml_get "$MOXIE_CONFIG" "gateway.endpoint" "") || true
|
|
607
|
+
[ -n "$cfg_endpoint" ] && endpoint="$cfg_endpoint"
|
|
608
|
+
fi
|
|
609
|
+
|
|
610
|
+
local json
|
|
611
|
+
json=$(GATEWAY_API_KEY="$api_key" node "$MOXIE_LIB/gateway-models.mjs" "$endpoint" "$filter" 2>&1) || {
|
|
612
|
+
echo "ERROR: Failed to fetch models from gateway." >&2
|
|
613
|
+
echo "$json" >&2
|
|
614
|
+
return 1
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
# Parse JSON with python3 for pretty display
|
|
618
|
+
python3 -c "
|
|
619
|
+
import json, sys
|
|
620
|
+
|
|
621
|
+
data = json.loads(sys.stdin.read())
|
|
622
|
+
models = data.get('models', [])
|
|
623
|
+
|
|
624
|
+
if not models:
|
|
625
|
+
print('No models found.' + (' Try a different filter.' if '$filter' else ''))
|
|
626
|
+
sys.exit(0)
|
|
627
|
+
|
|
628
|
+
# Group by provider
|
|
629
|
+
providers = {}
|
|
630
|
+
for m in models:
|
|
631
|
+
p = m['provider']
|
|
632
|
+
providers.setdefault(p, []).append(m)
|
|
633
|
+
|
|
634
|
+
# Hardcoded models for marking
|
|
635
|
+
hardcoded = set('''$(printf '%s\n' "${KNOWN_GATEWAY_MODELS[@]}")'''.strip().split('\n'))
|
|
636
|
+
|
|
637
|
+
total = len(models)
|
|
638
|
+
filter_note = ' matching \"$filter\"' if '$filter' else ''
|
|
639
|
+
print(f'Available gateway models ({total}{filter_note}):')
|
|
640
|
+
print()
|
|
641
|
+
|
|
642
|
+
for provider in sorted(providers.keys()):
|
|
643
|
+
pmodels = providers[provider]
|
|
644
|
+
print(f' \033[1m{provider}\033[0m ({len(pmodels)} models)')
|
|
645
|
+
for m in pmodels:
|
|
646
|
+
marker = ' \033[32m●\033[0m' if m['id'] in hardcoded else ' '
|
|
647
|
+
print(f' {marker} {m[\"id\"]}')
|
|
648
|
+
print()
|
|
649
|
+
|
|
650
|
+
print('\033[32m●\033[0m = currently in moxie defaults')
|
|
651
|
+
print()
|
|
652
|
+
print('To use any model, add it to .moxie/config.toml:')
|
|
653
|
+
print(' [agents.my-model]')
|
|
654
|
+
print(' type = \"gateway\"')
|
|
655
|
+
print(' model = \"provider/model-name\"')
|
|
656
|
+
print(' order = 10')
|
|
657
|
+
" <<< "$json"
|
|
658
|
+
}
|
|
659
|
+
|
|
557
660
|
# ---- Doctor: health checks ----
|
|
558
661
|
|
|
559
662
|
cmd_doctor() {
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// moxie/lib/gateway-models.mjs — List available models from Vercel AI Gateway
|
|
3
|
+
// Zero npm dependencies. Node 14+ compatible.
|
|
4
|
+
// Usage: GATEWAY_API_KEY=xxx node gateway-models.mjs [endpoint] [--filter provider]
|
|
5
|
+
|
|
6
|
+
import https from 'https';
|
|
7
|
+
import http from 'http';
|
|
8
|
+
|
|
9
|
+
const API_KEY = process.env.GATEWAY_API_KEY;
|
|
10
|
+
const endpoint = process.argv[2] || 'https://ai-gateway.vercel.sh';
|
|
11
|
+
const filter = process.argv[3] || '';
|
|
12
|
+
|
|
13
|
+
if (!API_KEY) { process.stderr.write('ERROR: GATEWAY_API_KEY not set\n'); process.exit(1); }
|
|
14
|
+
|
|
15
|
+
const url = new URL(`${endpoint}/v1/models`);
|
|
16
|
+
|
|
17
|
+
const isHttps = url.protocol === 'https:';
|
|
18
|
+
const mod = isHttps ? https : http;
|
|
19
|
+
|
|
20
|
+
const options = {
|
|
21
|
+
hostname: url.hostname,
|
|
22
|
+
port: url.port || (isHttps ? 443 : 80),
|
|
23
|
+
path: url.pathname + url.search,
|
|
24
|
+
method: 'GET',
|
|
25
|
+
headers: {
|
|
26
|
+
'Authorization': `Bearer ${API_KEY}`,
|
|
27
|
+
'Accept': 'application/json',
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const req = mod.request(options, (res) => {
|
|
32
|
+
let body = '';
|
|
33
|
+
res.on('data', (chunk) => { body += chunk; });
|
|
34
|
+
res.on('end', () => {
|
|
35
|
+
if (res.statusCode !== 200) {
|
|
36
|
+
process.stderr.write(`API error ${res.statusCode}: ${body.slice(0, 500)}\n`);
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
try {
|
|
41
|
+
const data = JSON.parse(body);
|
|
42
|
+
// OpenAI-compatible /v1/models returns { data: [...] }
|
|
43
|
+
let models = data.data || data.models || data || [];
|
|
44
|
+
if (!Array.isArray(models)) models = [];
|
|
45
|
+
|
|
46
|
+
// Normalize each model to { id, provider, name, created }
|
|
47
|
+
const normalized = models.map((m) => {
|
|
48
|
+
const id = m.id || m.model || '';
|
|
49
|
+
const parts = id.split('/');
|
|
50
|
+
const provider = parts.length > 1 ? parts[0] : (m.owned_by || 'unknown');
|
|
51
|
+
const name = parts.length > 1 ? parts.slice(1).join('/') : id;
|
|
52
|
+
return {
|
|
53
|
+
id,
|
|
54
|
+
provider,
|
|
55
|
+
name,
|
|
56
|
+
created: m.created || 0,
|
|
57
|
+
};
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// Apply filter if provided
|
|
61
|
+
const filtered = filter
|
|
62
|
+
? normalized.filter((m) => m.id.toLowerCase().includes(filter.toLowerCase()))
|
|
63
|
+
: normalized;
|
|
64
|
+
|
|
65
|
+
// Sort by provider, then name
|
|
66
|
+
filtered.sort((a, b) => {
|
|
67
|
+
if (a.provider !== b.provider) return a.provider.localeCompare(b.provider);
|
|
68
|
+
return a.name.localeCompare(b.name);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
process.stdout.write(JSON.stringify({ models: filtered }) + '\n');
|
|
72
|
+
} catch (err) {
|
|
73
|
+
process.stderr.write(`Failed to parse response: ${err.message}\n`);
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
req.on('error', (err) => {
|
|
80
|
+
process.stderr.write(`Network error: ${err.message}\n`);
|
|
81
|
+
process.exit(1);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
req.end();
|
package/lib/phases.sh
CHANGED
|
@@ -216,6 +216,7 @@ _select_context_docs() {
|
|
|
216
216
|
_select_agents() {
|
|
217
217
|
SELECTED_AGENT_INDICES=()
|
|
218
218
|
SELECTED_GATEWAY_INDICES=()
|
|
219
|
+
SELECTED_CUSTOM_GATEWAY_INDICES=()
|
|
219
220
|
|
|
220
221
|
# Build unified item list: CLI agents, separator, gateway models
|
|
221
222
|
local item_labels=()
|
|
@@ -262,6 +263,19 @@ _select_agents() {
|
|
|
262
263
|
[ "$len" -gt "$max_label_len" ] && max_label_len=$len
|
|
263
264
|
done
|
|
264
265
|
|
|
266
|
+
# Custom model entry point
|
|
267
|
+
item_labels+=("+ Add custom model...")
|
|
268
|
+
item_meta+=("type provider/model-name")
|
|
269
|
+
item_types+=("custom_add")
|
|
270
|
+
item_sources+=("-1")
|
|
271
|
+
local _custom_label="+ Add custom model..."
|
|
272
|
+
local len=${#_custom_label}
|
|
273
|
+
[ "$len" -gt "$max_label_len" ] && max_label_len=$len
|
|
274
|
+
|
|
275
|
+
# Track custom models added during this session
|
|
276
|
+
local custom_gateway_names=()
|
|
277
|
+
local custom_gateway_models=()
|
|
278
|
+
|
|
265
279
|
local count=${#item_labels[@]}
|
|
266
280
|
|
|
267
281
|
# State: pre-select CLI agents, gateway unselected
|
|
@@ -299,6 +313,10 @@ _select_agents() {
|
|
|
299
313
|
fi
|
|
300
314
|
local marker=" "
|
|
301
315
|
[ "$cursor" -eq "$i" ] && marker="> "
|
|
316
|
+
if [ "${item_types[$i]}" = "custom_add" ]; then
|
|
317
|
+
printf "\\r\\033[K %s \\033[36m%s\\033[0m \\033[2m(%s)\\033[0m\\n" "$marker" "${item_labels[$i]}" "${item_meta[$i]}" >&2
|
|
318
|
+
continue
|
|
319
|
+
fi
|
|
302
320
|
local check="[ ]"
|
|
303
321
|
[ "${selected[$i]}" = "1" ] && check="[x]"
|
|
304
322
|
if [ -n "${item_meta[$i]}" ]; then
|
|
@@ -318,7 +336,7 @@ _select_agents() {
|
|
|
318
336
|
printf "\\r\\033[K %s\\033[2m%s\\033[0m\\n" "$submit_marker" "Submit (need at least 2)" >&2
|
|
319
337
|
fi
|
|
320
338
|
|
|
321
|
-
printf "\\r\\033[K\\n\\033[K \\033[2m↑↓ navigate · space
|
|
339
|
+
printf "\\r\\033[K\\n\\033[K \\033[2m↑↓ navigate · space toggle · enter submit/add · 'moxie models' to browse\\033[0m" >&2
|
|
322
340
|
}
|
|
323
341
|
|
|
324
342
|
printf "Select agents (at least 2). CLI agents pre-selected, gateway models available below:\\n\\n" >&2
|
|
@@ -361,16 +379,82 @@ _select_agents() {
|
|
|
361
379
|
esac
|
|
362
380
|
fi
|
|
363
381
|
elif [ "$key" = " " ]; then
|
|
364
|
-
if [ "$cursor" -lt "$count" ] && [ "${item_types[$cursor]}" != "separator" ]; then
|
|
382
|
+
if [ "$cursor" -lt "$count" ] && [ "${item_types[$cursor]}" != "separator" ] && [ "${item_types[$cursor]}" != "custom_add" ]; then
|
|
365
383
|
[ "${selected[$cursor]}" = "0" ] && selected[$cursor]=1 || selected[$cursor]=0
|
|
366
384
|
fi
|
|
367
385
|
elif [ "$key" = "" ]; then
|
|
368
386
|
if [ "$cursor" -eq "$count" ]; then
|
|
387
|
+
# Submit
|
|
369
388
|
local sel_count=0
|
|
370
389
|
for (( i = 0; i < count; i++ )); do
|
|
371
390
|
[ "${selected[$i]}" = "1" ] && sel_count=$(( sel_count + 1 ))
|
|
372
391
|
done
|
|
373
392
|
[ "$sel_count" -ge 2 ] && break
|
|
393
|
+
elif [ "${item_types[$cursor]}" = "custom_add" ]; then
|
|
394
|
+
# Prompt for custom model string
|
|
395
|
+
printf "\\033[?25h" >&2
|
|
396
|
+
stty echo icanon < /dev/tty 2>/dev/null
|
|
397
|
+
printf "\\n\\r\\033[K Model ID (provider/model-name): " >&2
|
|
398
|
+
local custom_model=""
|
|
399
|
+
read -r custom_model < /dev/tty
|
|
400
|
+
stty -echo -icanon min 1 < /dev/tty 2>/dev/null
|
|
401
|
+
printf "\\033[?25l" >&2
|
|
402
|
+
|
|
403
|
+
if [ -n "$custom_model" ] && [[ "$custom_model" == */* ]]; then
|
|
404
|
+
# Derive a short name from the model ID: provider-modelbase
|
|
405
|
+
local custom_provider="${custom_model%%/*}"
|
|
406
|
+
local custom_name_part="${custom_model#*/}"
|
|
407
|
+
local custom_slug="${custom_provider}-${custom_name_part}"
|
|
408
|
+
# Sanitize slug for TOML key
|
|
409
|
+
custom_slug=$(echo "$custom_slug" | tr '[:upper:]' '[:lower:]' | tr ' .' '-' | tr -cd 'a-z0-9-')
|
|
410
|
+
custom_slug="${custom_slug}-gw"
|
|
411
|
+
|
|
412
|
+
# Insert before the custom_add row (which is at current cursor)
|
|
413
|
+
local insert_at=$cursor
|
|
414
|
+
|
|
415
|
+
# Shift arrays to insert new item
|
|
416
|
+
local new_labels=() new_meta=() new_types=() new_sources=() new_selected=()
|
|
417
|
+
for (( i = 0; i < count; i++ )); do
|
|
418
|
+
if [ "$i" -eq "$insert_at" ]; then
|
|
419
|
+
new_labels+=("$custom_name_part")
|
|
420
|
+
new_meta+=("$custom_model")
|
|
421
|
+
new_types+=("custom_gateway")
|
|
422
|
+
new_sources+=("${#custom_gateway_names[@]}")
|
|
423
|
+
new_selected+=(1)
|
|
424
|
+
fi
|
|
425
|
+
new_labels+=("${item_labels[$i]}")
|
|
426
|
+
new_meta+=("${item_meta[$i]}")
|
|
427
|
+
new_types+=("${item_types[$i]}")
|
|
428
|
+
new_sources+=("${item_sources[$i]}")
|
|
429
|
+
new_selected+=("${selected[$i]}")
|
|
430
|
+
done
|
|
431
|
+
|
|
432
|
+
item_labels=("${new_labels[@]}")
|
|
433
|
+
item_meta=("${new_meta[@]}")
|
|
434
|
+
item_types=("${new_types[@]}")
|
|
435
|
+
item_sources=("${new_sources[@]}")
|
|
436
|
+
selected=("${new_selected[@]}")
|
|
437
|
+
|
|
438
|
+
custom_gateway_names+=("$custom_slug")
|
|
439
|
+
custom_gateway_models+=("$custom_model")
|
|
440
|
+
|
|
441
|
+
count=${#item_labels[@]}
|
|
442
|
+
jump_back=$(( count + 3 ))
|
|
443
|
+
|
|
444
|
+
# Update max_label_len if needed
|
|
445
|
+
local len=${#custom_name_part}
|
|
446
|
+
[ "$len" -gt "$max_label_len" ] && max_label_len=$len
|
|
447
|
+
sep=""
|
|
448
|
+
for (( i = 0; i < max_label_len + 40; i++ )); do sep="${sep}-"; done
|
|
449
|
+
else
|
|
450
|
+
# Invalid — erase the prompt line
|
|
451
|
+
if [ -n "$custom_model" ]; then
|
|
452
|
+
printf "\\r\\033[K \\033[31mInvalid format. Use provider/model-name (e.g. anthropic/claude-sonnet-4-6)\\033[0m" >&2
|
|
453
|
+
sleep 1
|
|
454
|
+
fi
|
|
455
|
+
fi
|
|
456
|
+
# Erase the prompt lines and re-render
|
|
457
|
+
printf "\\033[2A" >&2
|
|
374
458
|
elif [ "${item_types[$cursor]}" != "separator" ]; then
|
|
375
459
|
[ "${selected[$cursor]}" = "0" ] && selected[$cursor]=1 || selected[$cursor]=0
|
|
376
460
|
fi
|
|
@@ -387,6 +471,10 @@ _select_agents() {
|
|
|
387
471
|
trap - INT TERM
|
|
388
472
|
printf "\\n\\n" >&2
|
|
389
473
|
|
|
474
|
+
# Export custom models for config writer
|
|
475
|
+
CUSTOM_GATEWAY_NAMES=("${custom_gateway_names[@]}")
|
|
476
|
+
CUSTOM_GATEWAY_MODELS=("${custom_gateway_models[@]}")
|
|
477
|
+
|
|
390
478
|
# Collect selections by type
|
|
391
479
|
local has_gateway=0
|
|
392
480
|
for (( i = 0; i < count; i++ )); do
|
|
@@ -397,6 +485,10 @@ _select_agents() {
|
|
|
397
485
|
SELECTED_GATEWAY_INDICES+=("${item_sources[$i]}")
|
|
398
486
|
has_gateway=1
|
|
399
487
|
;;
|
|
488
|
+
custom_gateway)
|
|
489
|
+
SELECTED_CUSTOM_GATEWAY_INDICES+=("${item_sources[$i]}")
|
|
490
|
+
has_gateway=1
|
|
491
|
+
;;
|
|
400
492
|
esac
|
|
401
493
|
done
|
|
402
494
|
|
|
@@ -406,6 +498,7 @@ _select_agents() {
|
|
|
406
498
|
gateway_store_key "vercel-ai-gateway" || {
|
|
407
499
|
echo "ERROR: Failed to store gateway key. Gateway models will not work." >&2
|
|
408
500
|
SELECTED_GATEWAY_INDICES=()
|
|
501
|
+
SELECTED_CUSTOM_GATEWAY_INDICES=()
|
|
409
502
|
}
|
|
410
503
|
fi
|
|
411
504
|
}
|
|
@@ -424,7 +517,10 @@ path = "spec.md"
|
|
|
424
517
|
HEADER
|
|
425
518
|
|
|
426
519
|
# Gateway section (if any gateway models selected)
|
|
427
|
-
|
|
520
|
+
local has_any_gw=0
|
|
521
|
+
[ ${#SELECTED_GATEWAY_INDICES[@]} -gt 0 ] && has_any_gw=1
|
|
522
|
+
[ ${#SELECTED_CUSTOM_GATEWAY_INDICES[@]} -gt 0 ] && has_any_gw=1
|
|
523
|
+
if [ "$has_any_gw" = "1" ]; then
|
|
428
524
|
local run_id
|
|
429
525
|
run_id="run-$(date +%Y%m%d-%H%M%S)-$$"
|
|
430
526
|
cat >> "$config_file" <<GATEWAY
|
|
@@ -458,7 +554,7 @@ AGENT
|
|
|
458
554
|
done
|
|
459
555
|
fi
|
|
460
556
|
|
|
461
|
-
# Gateway agents
|
|
557
|
+
# Gateway agents (built-in)
|
|
462
558
|
for idx in "${SELECTED_GATEWAY_INDICES[@]}"; do
|
|
463
559
|
local name="${KNOWN_GATEWAY_NAMES[$idx]}"
|
|
464
560
|
local model="${KNOWN_GATEWAY_MODELS[$idx]}"
|
|
@@ -468,6 +564,20 @@ type = "gateway"
|
|
|
468
564
|
model = "${model}"
|
|
469
565
|
order = ${order}
|
|
470
566
|
|
|
567
|
+
GWAGENT
|
|
568
|
+
order=$((order + 1))
|
|
569
|
+
done
|
|
570
|
+
|
|
571
|
+
# Custom gateway agents (added during init)
|
|
572
|
+
for idx in "${SELECTED_CUSTOM_GATEWAY_INDICES[@]}"; do
|
|
573
|
+
local name="${CUSTOM_GATEWAY_NAMES[$idx]}"
|
|
574
|
+
local model="${CUSTOM_GATEWAY_MODELS[$idx]}"
|
|
575
|
+
cat >> "$config_file" <<GWAGENT
|
|
576
|
+
[agents.${name}]
|
|
577
|
+
type = "gateway"
|
|
578
|
+
model = "${model}"
|
|
579
|
+
order = ${order}
|
|
580
|
+
|
|
471
581
|
GWAGENT
|
|
472
582
|
order=$((order + 1))
|
|
473
583
|
done
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zachjxyz/moxie",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.6",
|
|
4
4
|
"description": "Run multiple AI coding agents through spec-driven phases with quorum convergence. Supports CLI agents (Claude, Codex, Qwen, Aider, Goose, Amp, Cline, Roo) and Vercel AI Gateway models.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"moxie": "bin/moxie"
|