agentgui 1.0.974 → 1.0.976
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/lib/http-handler.js +11 -13
- package/package.json +1 -1
- package/scripts/validate-mutations.mjs +3 -0
- package/site/app/js/app.js +57 -33
- package/site/app/js/backend.js +1 -0
- package/site/app/vendor/anentrypoint-design/247420.css +6 -6
- package/site/app/vendor/anentrypoint-design/247420.js +12 -12
- package/test.js +0 -89
package/test.js
CHANGED
|
@@ -13,15 +13,6 @@ import { initializeDescriptors, getAgentDescriptor } from './lib/agent-descripto
|
|
|
13
13
|
import { createACPProtocolHandler } from './lib/acp-protocol.js';
|
|
14
14
|
import { sendJSON, compressAndSend, acceptsEncoding } from './lib/http-utils.js';
|
|
15
15
|
const require = createRequire(import.meta.url);
|
|
16
|
-
// lib/jsonl-parser.js was also removed in the pivot (ccsniff owns JSONL parsing
|
|
17
|
-
// now). Load it dynamically so its test skips rather than crashing the suite.
|
|
18
|
-
let JsonlParser = null;
|
|
19
|
-
try { ({ JsonlParser } = await import('./lib/jsonl-parser.js')); } catch { JsonlParser = null; }
|
|
20
|
-
// lib/db-queries.js was removed in the 2026-05-19 single-surface pivot (history
|
|
21
|
-
// now flows through ccsniff, not the local query layer). Import it dynamically
|
|
22
|
-
// so its absence skips only the db-queries tests instead of crashing the suite.
|
|
23
|
-
let createQueries = null;
|
|
24
|
-
try { ({ createQueries } = await import('./lib/db-queries.js')); } catch { createQueries = null; }
|
|
25
16
|
let Database, dbAvailable = false;
|
|
26
17
|
try {
|
|
27
18
|
try { Database = (await import('bun:sqlite')).default; }
|
|
@@ -33,10 +24,6 @@ let passed = 0, failed = 0, skipped = 0;
|
|
|
33
24
|
const ok = (name, fn) => Promise.resolve().then(fn).then(
|
|
34
25
|
() => { console.log(`ok - ${name}`); passed++; },
|
|
35
26
|
(err) => { console.error(`FAIL - ${name}: ${err.message}`); failed++; });
|
|
36
|
-
// Skip a test when sqlite is unavailable OR when it needs the removed db-queries layer.
|
|
37
|
-
const okDb = (name, fn) => (dbAvailable && createQueries)
|
|
38
|
-
? ok(name, fn)
|
|
39
|
-
: (console.log(`skip (${dbAvailable ? 'no db-queries' : 'no sqlite'}) - ${name}`), skipped++, Promise.resolve());
|
|
40
27
|
function inMemDb() {
|
|
41
28
|
const db = new Database(':memory:');
|
|
42
29
|
if (db.pragma) db.pragma('foreign_keys = ON'); else db.run('PRAGMA foreign_keys = ON');
|
|
@@ -66,32 +53,6 @@ await ok('codec: json roundtrip + wire-byte decode', () => {
|
|
|
66
53
|
await (dbAvailable ? ok : (n) => (console.log(`skip (no sqlite) - ${n}`), skipped++, Promise.resolve()))('db: init schema creates conversations table', () => {
|
|
67
54
|
assert.ok(inMemDb().db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='conversations'").get());
|
|
68
55
|
});
|
|
69
|
-
await okDb('db-queries: createConversation round-trip', () => {
|
|
70
|
-
const { db, prep, gid } = inMemDb();
|
|
71
|
-
const q = createQueries(db, prep, gid);
|
|
72
|
-
const c = q.createConversation('claude-code', 'Test', '/tmp', 'sonnet', null);
|
|
73
|
-
assert.equal(q.getConversation(c.id).title, 'Test');
|
|
74
|
-
assert.equal(q.getConversation(c.id).status, 'active');
|
|
75
|
-
});
|
|
76
|
-
await okDb('db-queries: archive + restore + streaming flag', () => {
|
|
77
|
-
const { db, prep, gid } = inMemDb();
|
|
78
|
-
const q = createQueries(db, prep, gid);
|
|
79
|
-
const c = q.createConversation('claude-code', 'A');
|
|
80
|
-
q.archiveConversation(c.id); assert.equal(q.getConversation(c.id).status, 'archived');
|
|
81
|
-
q.restoreConversation(c.id); assert.equal(q.getConversation(c.id).status, 'active');
|
|
82
|
-
q.setIsStreaming(c.id, true); assert.equal(q.getIsStreaming(c.id), true);
|
|
83
|
-
q.setIsStreaming(c.id, false); assert.equal(q.getIsStreaming(c.id), false);
|
|
84
|
-
});
|
|
85
|
-
await okDb('acp-queries: thread crud + search', () => {
|
|
86
|
-
const { db, prep, gid } = inMemDb();
|
|
87
|
-
const q = createQueries(db, prep, gid);
|
|
88
|
-
const t = q.createThread({ foo: 'bar' });
|
|
89
|
-
assert.deepEqual(q.getThread(t.thread_id).metadata, { foo: 'bar' });
|
|
90
|
-
q.patchThread(t.thread_id, { metadata: { foo: 'baz' }, status: 'active' });
|
|
91
|
-
assert.deepEqual(q.getThread(t.thread_id).metadata, { foo: 'baz' });
|
|
92
|
-
q.createThread({ kind: 'b' });
|
|
93
|
-
assert.equal(q.searchThreads({}).total, 2);
|
|
94
|
-
});
|
|
95
56
|
await ok('WsRouter: dispatch + 404 + error + legacy', async () => {
|
|
96
57
|
const router = new WsRouter();
|
|
97
58
|
router.handle('ping', async (p) => ({ pong: p.n }));
|
|
@@ -122,18 +83,6 @@ await ok('workflow-plugin + agent-registry hermes', async () => {
|
|
|
122
83
|
const h = registry.get('hermes');
|
|
123
84
|
assert.equal(h.protocol, 'acp'); assert.deepEqual(h.buildArgs(), ['acp']);
|
|
124
85
|
});
|
|
125
|
-
await okDb('delete-all: soft-deletes + wipes related', () => {
|
|
126
|
-
const { db, prep, gid } = inMemDb();
|
|
127
|
-
const q = createQueries(db, prep, gid);
|
|
128
|
-
const c1 = q.createConversation('claude-code', 'A');
|
|
129
|
-
q.createConversation('claude-code', 'B');
|
|
130
|
-
q.createSession(c1.id); q.createMessage(c1.id, 'user', 'hello');
|
|
131
|
-
const oL = console.log; console.log = () => {};
|
|
132
|
-
try { q.deleteAllConversations(); } finally { console.log = oL; }
|
|
133
|
-
assert.deepEqual(db.prepare('SELECT status, count(*) as c FROM conversations GROUP BY status').all(), [{ status: 'deleted', c: 2 }]);
|
|
134
|
-
assert.equal(db.prepare('SELECT count(*) as c FROM messages').get().c, 0);
|
|
135
|
-
assert.equal(q.getConversationsList().length, 0);
|
|
136
|
-
});
|
|
137
86
|
await ok('provider-config: maskKey + buildSystemPrompt', () => {
|
|
138
87
|
assert.equal(maskKey(''), '****'); assert.equal(maskKey('short'), '****'); assert.equal(maskKey('sk-abcd1234efgh'), '****efgh');
|
|
139
88
|
assert.equal(buildSystemPrompt('claude-code'), '');
|
|
@@ -173,44 +122,6 @@ await ok('http-utils: sendJSON + compressAndSend size threshold', () => {
|
|
|
173
122
|
const big = mockRes(); compressAndSend(req, big, 200, 'text/plain', 'x'.repeat(2000)); assert.equal(big.headers['Content-Encoding'], 'gzip');
|
|
174
123
|
const ng = mockRes(); compressAndSend({ headers: {} }, ng, 200, 'text/html', 'y'.repeat(2000)); assert.equal(ng.headers['Cache-Control'], 'no-store');
|
|
175
124
|
});
|
|
176
|
-
await (JsonlParser ? ok : (n) => (console.log(`skip (no jsonl-parser) - ${n}`), skipped++, Promise.resolve()))('jsonl-parser: register + remove + clear', () => {
|
|
177
|
-
const p = new JsonlParser({ broadcastSync: () => {}, queries: { getConversationByClaudeSessionId: () => null } });
|
|
178
|
-
p.registerSession('s1', 'c1', 'd1'); assert.equal(p._convMap.get('s1'), 'c1');
|
|
179
|
-
p.removeSid('s1'); assert.equal(p._convMap.has('s1'), false);
|
|
180
|
-
p.registerSession('s2', 'c2', 'd2'); p.clear(); assert.equal(p._convMap.size, 0);
|
|
181
|
-
});
|
|
182
|
-
await okDb('conv-routes+thread-routes+auth-config+util-routes', async () => {
|
|
183
|
-
const [{ register: rC }, { register: rT }, { register: rA }, { register: rU }] = await Promise.all(['./lib/routes-conversations.js','./lib/routes-threads.js','./lib/routes-auth-config.js','./lib/routes-util.js'].map(m => import(m)));
|
|
184
|
-
const { db: d2, prep: p2, gid: g2 } = inMemDb(); const q2 = createQueries(d2, p2, g2);
|
|
185
|
-
const sj2 = (req, res, c, data) => { res.statusCode = c; res.body = JSON.stringify(data); };
|
|
186
|
-
const pb2 = async (req) => req?._b || {}; const mr = () => mockRes();
|
|
187
|
-
const cR = rC({ sendJSON: sj2, parseBody: pb2, queries: q2, activeExecutions: new Map(), broadcastSync: () => {} });
|
|
188
|
-
const c1 = q2.createConversation('claude-code', 'T');
|
|
189
|
-
const lr = mr(); await cR['GET /api/conversations'](null, lr); assert.equal(lr.statusCode, 200);
|
|
190
|
-
const cr = mr(); await cR['POST /api/conversations']({ _b: { agentId: 'claude-code', title: 'N' } }, cr);
|
|
191
|
-
assert.equal(cr.statusCode, 201); const nid = JSON.parse(cr.body).conversation.id;
|
|
192
|
-
const gr = mr(); await cR._match('GET', `/api/conversations/${nid}`)(null, gr); assert.equal(gr.statusCode, 200);
|
|
193
|
-
const dr = mr(); await cR._match('DELETE', `/api/conversations/${nid}`)(null, dr); assert.equal(dr.statusCode, 200);
|
|
194
|
-
const nr = mr(); await cR._match('GET', '/api/conversations/nope')(null, nr); assert.equal(nr.statusCode, 404);
|
|
195
|
-
const ar = mr(); await cR._match('POST', `/api/conversations/${c1.id}/archive`)(null, ar); assert.equal(ar.statusCode, 200);
|
|
196
|
-
const rr = mr(); await cR._match('POST', `/api/conversations/${c1.id}/restore`)(null, rr); assert.equal(rr.statusCode, 200);
|
|
197
|
-
const tR = rT({ sendJSON: sj2, parseBody: pb2, queries: q2 });
|
|
198
|
-
const tr = mr(); await tR['POST /api/threads']({ _b: { metadata: { k: 1 } } }, tr); assert.equal(tr.statusCode, 201);
|
|
199
|
-
const tid = JSON.parse(tr.body).thread_id;
|
|
200
|
-
const tgr = mr(); await tR._match('GET', `/api/threads/${tid}`)(null, tgr); assert.equal(tgr.statusCode, 200);
|
|
201
|
-
const tpr = mr(); await tR._match('PATCH', `/api/threads/${tid}`)({ _b: { metadata: { k: 2 } } }, tpr); assert.equal(tpr.statusCode, 200);
|
|
202
|
-
const tsr = { statusCode: 0, writeHead: (c) => { tsr.statusCode = c; }, end: () => {} };
|
|
203
|
-
await tR._match('DELETE', `/api/threads/${tid}`)(null, tsr); assert.equal(tsr.statusCode, 204);
|
|
204
|
-
const ssr = mr(); await tR['POST /api/threads/search']({ _b: {} }, ssr); assert.equal(ssr.statusCode, 200);
|
|
205
|
-
const aR = rA({ sendJSON: sj2, parseBody: pb2, getProviderConfigs: () => ({ anthropic: { hasKey: false } }), saveProviderConfig: () => '/x' });
|
|
206
|
-
const agr = mr(); aR['GET /api/auth/configs'](null, agr); assert.equal(agr.statusCode, 200); assert.ok(JSON.parse(agr.body).anthropic !== undefined);
|
|
207
|
-
const br = mr(); await aR['POST /api/auth/save-config']({ _b: { providerId: '', apiKey: 'x' } }, br); assert.equal(br.statusCode, 400);
|
|
208
|
-
const sr = mr(); await aR['POST /api/auth/save-config']({ _b: { providerId: 'anthropic', apiKey: 'sk-123456789' } }, sr); assert.equal(sr.statusCode, 200);
|
|
209
|
-
const uR = rU({ sendJSON: sj2, parseBody: pb2, queries: q2, STARTUP_CWD: process.cwd(), PKG_VERSION: '1.0.0' });
|
|
210
|
-
const hr = mr(); await uR['GET /api/home'](null, hr); assert.equal(hr.statusCode, 200); assert.ok(JSON.parse(hr.body).home);
|
|
211
|
-
const vr = mr(); await uR['GET /api/version'](null, vr); assert.equal(vr.statusCode, 200);
|
|
212
|
-
const fr = mr(); await uR['POST /api/folders']({ _b: { path: process.cwd() } }, fr); assert.equal(fr.statusCode, 200); assert.ok(Array.isArray(JSON.parse(fr.body).folders));
|
|
213
|
-
});
|
|
214
125
|
console.log(`\n${passed} passed, ${failed} failed, ${skipped} skipped`);
|
|
215
126
|
process.exit(failed === 0 ? 0 : 1);
|
|
216
127
|
}; run();
|