agentgui 1.0.923 → 1.0.925
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/gmgui.cjs +2 -1
- package/package.json +4 -4
- package/test.js +46 -30
package/bin/gmgui.cjs
CHANGED
|
@@ -43,7 +43,8 @@ async function gmgui(args = []) {
|
|
|
43
43
|
|
|
44
44
|
const port = process.env.PORT || 3000;
|
|
45
45
|
const baseUrl = process.env.BASE_URL || '/gm';
|
|
46
|
-
const
|
|
46
|
+
const bunAvailable = (() => { try { return spawnSync('bun', ['--version'], { shell: true }).status === 0; } catch { return false; } })();
|
|
47
|
+
const runtime = bunAvailable ? 'bun' : 'node';
|
|
47
48
|
|
|
48
49
|
return new Promise((resolve, reject) => {
|
|
49
50
|
const ps = spawn(runtime, [path.join(projectRoot, 'server.js')], {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentgui",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.925",
|
|
4
4
|
"description": "Multi-agent ACP client with real-time communication",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "electron/main.js",
|
|
@@ -16,9 +16,9 @@
|
|
|
16
16
|
},
|
|
17
17
|
"homepage": "https://github.com/AnEntrypoint/agentgui#readme",
|
|
18
18
|
"scripts": {
|
|
19
|
-
"start": "node server.js",
|
|
19
|
+
"start": "bun server.js || node server.js",
|
|
20
20
|
"dev": "node server.js --watch",
|
|
21
|
-
"postinstall": "node scripts/patch-fsbrowse.js && node scripts/copy-vendor.js",
|
|
21
|
+
"postinstall": "node scripts/patch-fsbrowse.js && node scripts/copy-vendor.js && (cd node_modules/better-sqlite3 && node-gyp rebuild 2>/dev/null) || true",
|
|
22
22
|
"electron": "electron electron/main.js",
|
|
23
23
|
"electron:dev": "PORT=3000 electron electron/main.js"
|
|
24
24
|
},
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"@google/gemini-cli": "latest",
|
|
29
29
|
"@kilocode/cli": "latest",
|
|
30
30
|
"@lanmower/ccf": "^1.0.4",
|
|
31
|
-
"better-sqlite3": "^12.
|
|
31
|
+
"better-sqlite3": "^12.9.0",
|
|
32
32
|
"busboy": "^1.6.0",
|
|
33
33
|
"ccfollow": "^1.0.7",
|
|
34
34
|
"execa": "^9.6.1",
|
package/test.js
CHANGED
|
@@ -131,21 +131,13 @@ await ok('agent-descriptors: initialize + cache', () => {
|
|
|
131
131
|
assert.ok(d.specs.input.properties.model); assert.ok(d.specs.thread_state.properties.sessionId);
|
|
132
132
|
assert.equal(getAgentDescriptor('nope'), null);
|
|
133
133
|
});
|
|
134
|
-
await ok('ws-optimizer: high-priority
|
|
135
|
-
const opt = new WSOptimizer(); const
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
assert.equal(
|
|
139
|
-
opt.
|
|
140
|
-
|
|
141
|
-
await ok('ws-optimizer: low-priority batches via timer', async () => {
|
|
142
|
-
const opt = new WSOptimizer(); const sent = [];
|
|
143
|
-
const ws = { readyState: 1, clientId: 'c2', latencyTier: 'excellent', send: (b) => sent.push(decode(b)) };
|
|
144
|
-
opt.sendToClient(ws, { type: 'tts_audio', n: 1 }); opt.sendToClient(ws, { type: 'tts_audio', n: 2 });
|
|
145
|
-
assert.equal(sent.length, 0);
|
|
146
|
-
await new Promise(r => setTimeout(r, 40));
|
|
147
|
-
assert.equal(sent.length, 1); assert.equal(sent[0].length, 2);
|
|
148
|
-
opt.removeClient(ws);
|
|
134
|
+
await ok('ws-optimizer: high-priority flush + low-priority batch', async () => {
|
|
135
|
+
const opt = new WSOptimizer(); const s1 = []; const s2 = [];
|
|
136
|
+
const w1 = { readyState: 1, clientId: 'c1', send: (b) => s1.push(decode(b)) };
|
|
137
|
+
const w2 = { readyState: 1, clientId: 'c2', latencyTier: 'excellent', send: (b) => s2.push(decode(b)) };
|
|
138
|
+
opt.sendToClient(w1, { type: 'streaming_start', id: 1 }); assert.equal(s1.length, 1); opt.removeClient(w1); assert.equal(opt.getStats().clients, 0);
|
|
139
|
+
opt.sendToClient(w2, { type: 'tts_audio', n: 1 }); opt.sendToClient(w2, { type: 'tts_audio', n: 2 }); assert.equal(s2.length, 0);
|
|
140
|
+
await new Promise(r => setTimeout(r, 40)); assert.equal(s2.length, 1); assert.equal(s2[0].length, 2); opt.removeClient(w2);
|
|
149
141
|
});
|
|
150
142
|
await ok('acp-protocol: session/update + result + error mapping', () => {
|
|
151
143
|
const h = createACPProtocolHandler(); const ctx = { sessionId: 's1' };
|
|
@@ -161,23 +153,47 @@ await ok('acp-protocol: session/update + result + error mapping', () => {
|
|
|
161
153
|
await ok('http-utils: sendJSON + compressAndSend size threshold', () => {
|
|
162
154
|
const req = { headers: { 'accept-encoding': 'gzip, deflate' } };
|
|
163
155
|
assert.equal(acceptsEncoding(req, 'gzip'), true); assert.equal(acceptsEncoding({ headers: {} }, 'gzip'), false);
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
assert.
|
|
167
|
-
const big = mockRes(); compressAndSend(req, big, 200, 'text/plain', 'x'.repeat(2000));
|
|
168
|
-
assert.equal(big.headers['Content-Encoding'], 'gzip');
|
|
169
|
-
const noGz = mockRes(); compressAndSend({ headers: {} }, noGz, 200, 'text/html', 'y'.repeat(2000));
|
|
170
|
-
assert.equal(noGz.headers['Cache-Control'], 'no-store'); assert.ok(!noGz.headers['Content-Encoding']);
|
|
156
|
+
const sm = mockRes(); sendJSON(req, sm, 200, { ok: 1 }); assert.equal(sm.statusCode, 200); assert.equal(sm.headers['Content-Type'], 'application/json');
|
|
157
|
+
const big = mockRes(); compressAndSend(req, big, 200, 'text/plain', 'x'.repeat(2000)); assert.equal(big.headers['Content-Encoding'], 'gzip');
|
|
158
|
+
const ng = mockRes(); compressAndSend({ headers: {} }, ng, 200, 'text/html', 'y'.repeat(2000)); assert.equal(ng.headers['Cache-Control'], 'no-store');
|
|
171
159
|
});
|
|
172
160
|
await ok('jsonl-parser: register + remove + clear', () => {
|
|
173
|
-
const
|
|
174
|
-
|
|
175
|
-
p.
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
161
|
+
const p = new JsonlParser({ broadcastSync: () => {}, queries: { getConversationByClaudeSessionId: () => null } });
|
|
162
|
+
p.registerSession('s1', 'c1', 'd1'); assert.equal(p._convMap.get('s1'), 'c1');
|
|
163
|
+
p.removeSid('s1'); assert.equal(p._convMap.has('s1'), false);
|
|
164
|
+
p.registerSession('s2', 'c2', 'd2'); p.clear(); assert.equal(p._convMap.size, 0);
|
|
165
|
+
});
|
|
166
|
+
await okDb('conv-routes+thread-routes+auth-config+util-routes', async () => {
|
|
167
|
+
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)));
|
|
168
|
+
const { db: d2, prep: p2, gid: g2 } = inMemDb(); const q2 = createQueries(d2, p2, g2);
|
|
169
|
+
const sj2 = (req, res, c, data) => { res.statusCode = c; res.body = JSON.stringify(data); };
|
|
170
|
+
const pb2 = async (req) => req?._b || {}; const mr = () => mockRes();
|
|
171
|
+
const cR = rC({ sendJSON: sj2, parseBody: pb2, queries: q2, activeExecutions: new Map(), broadcastSync: () => {} });
|
|
172
|
+
const c1 = q2.createConversation('claude-code', 'T');
|
|
173
|
+
const lr = mr(); await cR['GET /api/conversations'](null, lr); assert.equal(lr.statusCode, 200);
|
|
174
|
+
const cr = mr(); await cR['POST /api/conversations']({ _b: { agentId: 'claude-code', title: 'N' } }, cr);
|
|
175
|
+
assert.equal(cr.statusCode, 201); const nid = JSON.parse(cr.body).conversation.id;
|
|
176
|
+
const gr = mr(); await cR._match('GET', `/api/conversations/${nid}`)(null, gr); assert.equal(gr.statusCode, 200);
|
|
177
|
+
const dr = mr(); await cR._match('DELETE', `/api/conversations/${nid}`)(null, dr); assert.equal(dr.statusCode, 200);
|
|
178
|
+
const nr = mr(); await cR._match('GET', '/api/conversations/nope')(null, nr); assert.equal(nr.statusCode, 404);
|
|
179
|
+
const ar = mr(); await cR._match('POST', `/api/conversations/${c1.id}/archive`)(null, ar); assert.equal(ar.statusCode, 200);
|
|
180
|
+
const rr = mr(); await cR._match('POST', `/api/conversations/${c1.id}/restore`)(null, rr); assert.equal(rr.statusCode, 200);
|
|
181
|
+
const tR = rT({ sendJSON: sj2, parseBody: pb2, queries: q2 });
|
|
182
|
+
const tr = mr(); await tR['POST /api/threads']({ _b: { metadata: { k: 1 } } }, tr); assert.equal(tr.statusCode, 201);
|
|
183
|
+
const tid = JSON.parse(tr.body).thread_id;
|
|
184
|
+
const tgr = mr(); await tR._match('GET', `/api/threads/${tid}`)(null, tgr); assert.equal(tgr.statusCode, 200);
|
|
185
|
+
const tpr = mr(); await tR._match('PATCH', `/api/threads/${tid}`)({ _b: { metadata: { k: 2 } } }, tpr); assert.equal(tpr.statusCode, 200);
|
|
186
|
+
const tsr = { statusCode: 0, writeHead: (c) => { tsr.statusCode = c; }, end: () => {} };
|
|
187
|
+
await tR._match('DELETE', `/api/threads/${tid}`)(null, tsr); assert.equal(tsr.statusCode, 204);
|
|
188
|
+
const ssr = mr(); await tR['POST /api/threads/search']({ _b: {} }, ssr); assert.equal(ssr.statusCode, 200);
|
|
189
|
+
const aR = rA({ sendJSON: sj2, parseBody: pb2, getProviderConfigs: () => ({ anthropic: { hasKey: false } }), saveProviderConfig: () => '/x' });
|
|
190
|
+
const agr = mr(); aR['GET /api/auth/configs'](null, agr); assert.equal(agr.statusCode, 200); assert.ok(JSON.parse(agr.body).anthropic !== undefined);
|
|
191
|
+
const br = mr(); await aR['POST /api/auth/save-config']({ _b: { providerId: '', apiKey: 'x' } }, br); assert.equal(br.statusCode, 400);
|
|
192
|
+
const sr = mr(); await aR['POST /api/auth/save-config']({ _b: { providerId: 'anthropic', apiKey: 'sk-123456789' } }, sr); assert.equal(sr.statusCode, 200);
|
|
193
|
+
const uR = rU({ sendJSON: sj2, parseBody: pb2, queries: q2, STARTUP_CWD: process.cwd(), PKG_VERSION: '1.0.0' });
|
|
194
|
+
const hr = mr(); await uR['GET /api/home'](null, hr); assert.equal(hr.statusCode, 200); assert.ok(JSON.parse(hr.body).home);
|
|
195
|
+
const vr = mr(); await uR['GET /api/version'](null, vr); assert.equal(vr.statusCode, 200);
|
|
196
|
+
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));
|
|
181
197
|
});
|
|
182
198
|
console.log(`\n${passed} passed, ${failed} failed`);
|
|
183
199
|
process.exit(failed === 0 ? 0 : 1);
|