-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsmoke_test.mjs
More file actions
163 lines (131 loc) · 7.67 KB
/
Copy pathsmoke_test.mjs
File metadata and controls
163 lines (131 loc) · 7.67 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
import { startServer } from "./agent_server.mjs";
import fs from "fs";
async function must(ok, msg) {
if (!ok) throw new Error(msg);
}
const SMOKE_AUTH_TOKEN = "test-smoke-auth-token-123456789012345";
const AUTH_HEADERS = { authorization: `Bearer ${SMOKE_AUTH_TOKEN}` };
process.env.DIZZY_TOOL_ALLOW_LOCALHOST = "1";
delete process.env.DIZZY_CHAT_BACKEND;
delete process.env.GEMINI_API_KEY;
delete process.env.GEMINI_MODEL;
delete process.env.DIZZY_CHAT_FALLBACK_BACKEND;
delete process.env.OPENAI_COMPAT_BASE_URL;
delete process.env.OPENAI_COMPAT_API_KEY;
delete process.env.OPENAI_COMPAT_MODEL;
process.env.DIZZY_TRAJECTORY_PATH = "runtime/test-smoke-trajectories.jsonl";
process.env.DIZZY_FRICTION_PATH = "runtime/test-smoke-friction.jsonl";
const started = await startServer({
port: 0,
redisUrl: "",
memoryGraphEnabled: true,
authToken: SMOKE_AUTH_TOKEN,
});
try {
const port = started.boundPort;
const health = await fetch(`http://127.0.0.1:${port}/health`).then((r) => r.json());
await must(health.ok === true, "health not ok");
const prompt = await fetch(`http://127.0.0.1:${port}/prompt`, { headers: AUTH_HEADERS }).then((r) => r.json());
await must(prompt.ok === true, "prompt not ok");
await must(prompt.prompt_budget?.constitutional_files >= 1, "prompt budget missing constitutional count");
const profile = await fetch(`http://127.0.0.1:${port}/agent/profile`, { headers: AUTH_HEADERS }).then((r) => r.json());
await must(typeof profile.avatar_url === "string" && profile.avatar_url.includes("/assets/logo"), "profile avatar missing");
const gov = await fetch(`http://127.0.0.1:${port}/governance`, { headers: AUTH_HEADERS }).then((r) => r.text());
await must(gov.includes("INTERACTION_NORMS.md"), "governance doc missing");
const disabledDashboard = await fetch(`http://127.0.0.1:${port}/api/dashboard-data`, { headers: AUTH_HEADERS });
await must(disabledDashboard.status === 404, `expected disabled dashboard, got ${disabledDashboard.status}`);
const memoryGraph = await fetch(`http://127.0.0.1:${port}/memory/graph`, { headers: AUTH_HEADERS }).then((r) => r.json());
await must(memoryGraph.ok === true && memoryGraph.mode === "summary", "memory graph summary missing");
const memoryQuery = await fetch(`http://127.0.0.1:${port}/memory/graph?q=wikimedia`, { headers: AUTH_HEADERS }).then((r) => r.json());
await must(memoryQuery.ok === true && memoryQuery.mode === "query", "memory graph query missing");
const r1 = await fetch(`http://127.0.0.1:${port}/dispatch/incoming`, {
method: "POST",
headers: { ...AUTH_HEADERS, "content-type": "application/json" },
body: JSON.stringify({ channel: "smoke", text: "hello" }),
}).then((r) => r.json());
await must(r1.ok === true && r1.kind === "reply", `unexpected reply: ${JSON.stringify(r1)}`);
await must(
typeof r1.text === "string" && r1.text.includes("Chat backend is not configured"),
`unexpected degraded-mode text: ${JSON.stringify(r1)}`,
);
await must(
r1.text.includes("runtime/conversations/smoke.jsonl"),
`degraded-mode reply missing conversation path: ${JSON.stringify(r1)}`,
);
const r2 = await fetch(`http://127.0.0.1:${port}/dispatch/incoming`, {
method: "POST",
headers: { ...AUTH_HEADERS, "content-type": "application/json" },
body: JSON.stringify({ channel: "smoke", text: `tool:http_get http://127.0.0.1:${port}/health` }),
}).then((r) => r.json());
// With redisUrl unset, tool requests run inline by default.
await must(r2.ok === true && (r2.kind === "reply" || r2.kind === "ack"), `unexpected tool result: ${JSON.stringify(r2)}`);
const trajectory = await fetch(`http://127.0.0.1:${port}/dispatch/incoming`, {
method: "POST",
headers: { ...AUTH_HEADERS, "content-type": "application/json" },
body: JSON.stringify({
channel: "local",
text: '/trajectory add {"goal":"Smoke test manual trajectory capture","success_criteria":"Runtime accepts sparse known-good pattern","actions_taken":["sent command"],"outcome":"success","reusable_pattern":"Keep manual learning capture explicit before automating it","reuse_tags":["smoke","trajectory"],"strength":7}',
}),
}).then((r) => r.json());
await must(trajectory.ok === true && trajectory.text.includes("Saved trajectory"), `unexpected trajectory result: ${JSON.stringify(trajectory)}`);
const friction = await fetch(`http://127.0.0.1:${port}/dispatch/incoming`, {
method: "POST",
headers: { ...AUTH_HEADERS, "content-type": "application/json" },
body: JSON.stringify({
channel: "local",
text: '/friction add {"friction_type":"disruption","description":"Smoke test logged a recoverable disruption","task_context":"runtime smoke","severity":3,"frequency":"first"}',
}),
}).then((r) => r.json());
await must(friction.ok === true && friction.text.includes("Saved friction"), `unexpected friction result: ${JSON.stringify(friction)}`);
console.log("SMOKE_OK");
} finally {
await started.stop();
await fs.promises.rm("runtime/test-smoke-trajectories.jsonl", { force: true });
await fs.promises.rm("runtime/test-smoke-friction.jsonl", { force: true });
}
const authed = await startServer({
port: 0,
redisUrl: "",
authToken: SMOKE_AUTH_TOKEN,
dashboardEnabled: true,
});
try {
const port = authed.boundPort;
const unauthPrompt = await fetch(`http://127.0.0.1:${port}/prompt`);
await must(unauthPrompt.status === 401, `expected unauthorized prompt, got ${unauthPrompt.status}`);
const authedPrompt = await fetch(`http://127.0.0.1:${port}/prompt`, {
headers: AUTH_HEADERS,
}).then((r) => r.json());
await must(authedPrompt.ok === true, "authorized prompt not ok");
const unauthDashboard = await fetch(`http://127.0.0.1:${port}/api/dashboard-data`);
await must(unauthDashboard.status === 401, `expected unauthorized dashboard, got ${unauthDashboard.status}`);
const loginResp = await fetch(`http://127.0.0.1:${port}/dashboard/session`, {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded", ...AUTH_HEADERS },
body: `token=${SMOKE_AUTH_TOKEN}`,
redirect: "manual"
});
const cookieHeader = loginResp.headers.get("set-cookie") || "";
const sessionCookie = cookieHeader.split(";")[0];
const dashHtml = await fetch(`http://127.0.0.1:${port}/dashboard`, {
headers: { ...AUTH_HEADERS, "Cookie": sessionCookie },
}).then((r) => r.text());
await must(dashHtml.includes("Drift & Memory Dashboard"), "dashboard html missing title");
const dashData = await fetch(`http://127.0.0.1:${port}/api/dashboard-data`, {
headers: { ...AUTH_HEADERS, "Cookie": sessionCookie },
}).then((r) => r.json());
await must(dashData.ok === true && Array.isArray(dashData.prompt_sources) && Array.isArray(dashData.docs), "dashboard data invalid");
await must(dashData.projection === "minimal-v1", "dashboard data projection missing");
await must(dashData.docs.every((doc) => /^doc-[a-f0-9]{12}$/.test(doc.id) && !("path" in doc) && !("relPath" in doc)), "dashboard data leaked document paths");
const dashQuery = await fetch(`http://127.0.0.1:${port}/api/dashboard-query?q=apples`, {
headers: { ...AUTH_HEADERS, "Cookie": sessionCookie },
}).then((r) => r.json());
await must(dashQuery.ok === true && Array.isArray(dashQuery.snippets), "dashboard query invalid");
await must(dashQuery.snippets.length > 0, "dashboard query returned no matches");
await must(dashQuery.snippets.every((snippet) => /^doc-[a-f0-9]{12}$/.test(snippet.id) && !("path" in snippet)), "dashboard query leaked document paths");
const authHealth = await fetch(`http://127.0.0.1:${port}/health`).then((r) => r.json());
await must(authHealth.ok === true, "health should stay open on loopback binding");
console.log("SMOKE_AUTH_OK");
} finally {
await authed.stop();
}