forked from paradigmxyz/centaur
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathJustfile
More file actions
205 lines (175 loc) · 6.92 KB
/
Justfile
File metadata and controls
205 lines (175 loc) · 6.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
set dotenv-load := true
namespace := env_var_or_default("CENTAUR_NAMESPACE", "centaur")
release := env_var_or_default("CENTAUR_RELEASE", "centaur")
source := env_var_or_default("CENTAUR_IMAGE_SOURCE", "local")
chart := "contrib/chart"
dev_values := "contrib/chart/values.dev.yaml"
default:
just --list
build:
#!/usr/bin/env bash
set -euo pipefail
if [[ "${JUST_BUILD_SEQUENTIAL:-0}" =~ ^(1|true|yes)$ ]]; then
just _build-all-sequential
else
pids=()
for recipe in _build-api _build-iron-proxy _build-slackbot _build-chatbot _build-agent; do
just "$recipe" &
pids+=("$!")
done
status=0
for pid in "${pids[@]}"; do
wait "$pid" || status=1
done
exit "$status"
fi
_build-all-sequential:
just _build-api
just _build-iron-proxy
just _build-slackbot
just _build-chatbot
just _build-agent
build-one service:
#!/usr/bin/env bash
set -euo pipefail
case "{{service}}" in
api) just _build-api ;;
iron-proxy) just _build-iron-proxy ;;
slackbot) just _build-slackbot ;;
chatbot) just _build-chatbot ;;
agent|sandbox) just _build-agent ;;
*) echo "unknown service: {{service}}" >&2; exit 2 ;;
esac
_build-api:
docker build -t centaur-api:latest -f services/api/Dockerfile .
_build-iron-proxy:
docker build -t centaur-iron-proxy:latest -f services/iron-proxy/Dockerfile .
_build-slackbot:
docker build -t centaur-slackbot:latest -f services/slackbot/Dockerfile .
_build-chatbot:
docker build -t centaur-chatbot:latest -f services/chatbot/Dockerfile .
_build-agent:
docker build --target sandbox -t centaur-agent:latest -f services/sandbox/Dockerfile .
bootstrap-secrets *args:
contrib/scripts/bootstrap-k8s-secrets.sh --namespace {{namespace}} {{args}}
deploy:
#!/usr/bin/env bash
set -euo pipefail
helm dependency update {{chart}} >/dev/null
extra_args=()
case "{{source}}" in
local) ;;
ghcr)
extra_args+=(
--set api.image.repository=ghcr.io/paradigmxyz/centaur-api
--set ironProxy.image.repository=ghcr.io/paradigmxyz/centaur-iron-proxy
--set slackbot.image.repository=ghcr.io/paradigmxyz/centaur-slackbot
--set sandbox.image.repository=ghcr.io/paradigmxyz/centaur-agent
)
;;
*) echo "unknown source: {{source}} (expected local or ghcr)" >&2; exit 2 ;;
esac
if [[ -n "${OP_CONNECT_CREDENTIALS_FILE:-}" ]]; then
extra_args+=(
--set ironProxy.secretSource=onepassword-connect
--set onepasswordConnect.connect.create=true
)
fi
if [[ -n "${CODEX_AUTH_MODE:-}" ]]; then
extra_args+=(
--set sandbox.extraEnv.CODEX_AUTH_MODE=${CODEX_AUTH_MODE}
)
fi
helm upgrade --install {{release}} {{chart}} -n {{namespace}} --create-namespace -f {{dev_values}} ${extra_args[@]+"${extra_args[@]}"}
up:
#!/usr/bin/env bash
set -euo pipefail
just bootstrap-secrets
case "{{source}}" in
local) just build ;;
ghcr) ;;
*) echo "unknown source: {{source}} (expected local or ghcr)" >&2; exit 2 ;;
esac
just source={{source}} deploy
down:
kubectl delete namespace {{namespace}} --ignore-not-found --wait
reinstall:
just down
just up
status:
kubectl get all -n {{namespace}}
logs component:
kubectl logs -n {{namespace}} deploy/{{release}}-centaur-{{component}} --tail=200 -f
slack-thread-logs slack_link since="24h":
CENTAUR_NAMESPACE={{namespace}} CENTAUR_RELEASE={{release}} bash services/slackbot/scripts/slack-thread-logs.sh "{{slack_link}}" "{{since}}"
slack-thread-report slack_link:
CENTAUR_NAMESPACE={{namespace}} CENTAUR_RELEASE={{release}} bash services/slackbot/scripts/slack-thread-report.sh "{{slack_link}}"
cleanup-orphan-proxy-services mode="dry-run":
#!/usr/bin/env bash
set -euo pipefail
case "{{mode}}" in
dry-run|delete) ;;
*) echo "mode must be dry-run or delete" >&2; exit 2 ;;
esac
live_sandboxes="$(mktemp)"
trap 'rm -f "$live_sandboxes"' EXIT
kubectl -n {{namespace}} get pod -l centaur.ai/managed=true \
-o jsonpath='{range .items[*]}{.metadata.labels.centaur\.ai/sandbox-id}{"\n"}{end}' \
| sort -u > "$live_sandboxes"
found=0
while IFS=$'\t' read -r service sandbox_id; do
[[ -n "$service" && -n "$sandbox_id" ]] || continue
[[ "$sandbox_id" != "api" ]] || continue
if grep -qx "$sandbox_id" "$live_sandboxes"; then
continue
fi
found=1
if [[ "{{mode}}" == "delete" ]]; then
kubectl -n {{namespace}} delete svc "$service"
else
printf 'orphan proxy service: %s sandbox_id=%s\n' "$service" "$sandbox_id"
fi
done < <(
kubectl -n {{namespace}} get svc -l centaur.ai/iron-proxy=true \
-o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.metadata.labels.centaur\.ai/sandbox-id}{"\n"}{end}'
)
if [[ "$found" -eq 0 ]]; then
echo "No orphan proxy services found."
fi
shell component:
kubectl exec -it -n {{namespace}} deploy/{{release}}-centaur-{{component}} -- sh
smoke:
#!/usr/bin/env bash
set -euo pipefail
THREAD_KEY="smoke-$(date +%s)"
API_DEPLOY="deploy/{{release}}-centaur-api"
SPAWN=$(kubectl exec -n {{namespace}} "$API_DEPLOY" -- curl -s -X POST http://localhost:8000/agent/spawn \
-H "Content-Type: application/json" \
-d "{\"thread_key\":\"${THREAD_KEY}\"}")
ASSIGNMENT_GENERATION=$(printf '%s' "$SPAWN" | jq -r '.assignment_generation')
kubectl exec -n {{namespace}} "$API_DEPLOY" -- curl -s -X POST http://localhost:8000/agent/message \
-H "Content-Type: application/json" \
-d "{\"thread_key\":\"${THREAD_KEY}\",\"assignment_generation\":${ASSIGNMENT_GENERATION},\"role\":\"user\",\"parts\":[{\"type\":\"text\",\"text\":\"Reply with exactly PONG and nothing else.\"}]}" >/dev/null
EXECUTE=$(kubectl exec -n {{namespace}} "$API_DEPLOY" -- curl -s -X POST http://localhost:8000/agent/execute \
-H "Content-Type: application/json" \
-d "{\"thread_key\":\"${THREAD_KEY}\",\"assignment_generation\":${ASSIGNMENT_GENERATION},\"delivery\":{\"platform\":\"dev\"}}")
EXECUTION_ID=$(printf '%s' "$EXECUTE" | jq -r '.execution_id')
for _ in $(seq 1 60); do
STATE=$(kubectl exec -n {{namespace}} "$API_DEPLOY" -- curl -s "http://localhost:8000/agent/executions/${EXECUTION_ID}")
STATUS=$(printf '%s' "$STATE" | jq -r '.status // empty')
case "$STATUS" in
completed)
printf '%s\n' "$STATE" | jq
printf '%s\n' "$STATE" | jq -e '.result_text | contains("PONG")' >/dev/null
exit 0
;;
failed|failed_permanent|cancelled)
printf '%s\n' "$STATE" | jq
exit 1
;;
esac
sleep 2
done
kubectl exec -n {{namespace}} "$API_DEPLOY" -- curl -s "http://localhost:8000/agent/executions/${EXECUTION_ID}" | jq
echo "smoke timed out waiting for execution ${EXECUTION_ID}" >&2
exit 1