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
name: "HTTP API Interrupt endpoint"
description: |
Verify POST /sessions/:id/interrupt behaves correctly:
- Returns 200 + JSON {"interrupted": true/false} for a valid session
(even when no agent run is currently active).
- Returns 404 for a non-existent session.
No LLM turn is executed; this purely exercises the interrupt route
contract added in Goal 170.
sequential: true
setup:
- name: "Kill any leftover server on port 9093"
ignoreError: true
exec:
container: recursive-e2e
command: |
# Allocate a free port for this suite (host-mode port randomization).
PORT=$(python3 -c "import socket; s=socket.socket(); s.bind(('',0)); p=s.getsockname()[1]; s.close(); print(p)")
echo "$PORT" > /tmp/e2e-host-port-19.txt
echo "suite-port=$PORT"
export PORT=$(cat /tmp/e2e-host-port-19.txt)
pkill -f 'recursive.*http --addr' 2>/dev/null || true
sleep 1
echo cleaned
- name: "Reset state files"
ignoreError: true
exec:
container: recursive-e2e
command: export PORT=$(cat /tmp/e2e-host-port-19.txt); rm -f /tmp/intr-sid /tmp/intr-http.log && echo reset
- name: "Start HTTP server on port 9093"
exec:
container: recursive-e2e
command: |
export PORT=$(cat /tmp/e2e-host-port-19.txt)
RECURSIVE_HTTP_AUTH_KEYS=test-secret-key nohup recursive \
--api-base http://aimock:4010/v1 \
--api-key mock-key -m mock-chat \
http --addr 0.0.0.0:$PORT \
> /tmp/intr-http.log 2>&1 &
sleep 2
echo started
- name: "Sanity: GET /health returns ok"
exec:
container: recursive-e2e
command: export PORT=$(cat /tmp/e2e-host-port-19.txt); curl -sf http://localhost:$PORT/health
expect:
exitCode: 0
output:
contains: "ok"
- name: "Create session, save id to /tmp/intr-sid"
exec:
container: recursive-e2e
command: >
export PORT=$(cat /tmp/e2e-host-port-19.txt); curl -sf -X POST -H 'X-API-Key: test-secret-key' http://localhost:$PORT/sessions
-H 'Content-Type: application/json'
-d '{"system_prompt":"You are a test assistant."}'
| jq -r .id > /tmp/intr-sid
&& echo created=$(cat /tmp/intr-sid)
expect:
exitCode: 0
output:
contains: "created="
cases:
- name: "POST /sessions/:id/interrupt returns 200 for a valid session"
exec:
container: recursive-e2e
command: >
export PORT=$(cat /tmp/e2e-host-port-19.txt); SID=$(cat /tmp/intr-sid)
&& curl -s -o /dev/null -w 'status=%{http_code}'
-X POST -H 'X-API-Key: test-secret-key' http://localhost:$PORT/sessions/$SID/interrupt
-H 'Content-Type: application/json'
expect:
exitCode: 0
output:
contains: "status=200"
- name: "POST /sessions/:id/interrupt response contains interrupted field"
exec:
container: recursive-e2e
command: >
export PORT=$(cat /tmp/e2e-host-port-19.txt); SID=$(cat /tmp/intr-sid)
&& curl -sf -X POST -H 'X-API-Key: test-secret-key' http://localhost:$PORT/sessions/$SID/interrupt
-H 'Content-Type: application/json'
expect:
exitCode: 0
output:
contains: "interrupted"
- name: "POST /sessions/nonexistent/interrupt returns 404"
exec:
container: recursive-e2e
command: >
export PORT=$(cat /tmp/e2e-host-port-19.txt); curl -s -o /dev/null -w 'status=%{http_code}'
-X POST -H 'X-API-Key: test-secret-key' http://localhost:$PORT/sessions/no-such-session-xyz/interrupt
-H 'Content-Type: application/json'
expect:
exitCode: 0
output:
contains: "status=404"
teardown:
- name: "Stop HTTP server on 9093 and clean up"
ignoreError: true
exec:
container: recursive-e2e
command: |
export PORT=$(cat /tmp/e2e-host-port-19.txt)
pkill -f 'recursive.*http --addr' 2>/dev/null || true
rm -f /tmp/intr-sid /tmp/intr-http.log
echo stopped