agentgui 1.0.931 → 1.0.933
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/AGENTS.md +17 -12
- package/database.js +31 -2
- package/lib/http-handler.js +11 -25
- package/lib/routes-registry.js +4 -48
- package/lib/server-startup.js +3 -11
- package/lib/ws-setup.js +2 -1
- package/package.json +3 -3
- package/server.js +7 -1
- package/site/app/index.html +2 -2
- package/site/app/js/app.js +91 -86
- package/site/app/js/backend.js +1 -1
- package/static/lib/xstate.umd.min.js +1 -1
- package/lib/db-queries-chunks.js +0 -195
- package/lib/db-queries-chunks2.js +0 -82
- package/lib/db-queries-cleanup.js +0 -74
- package/lib/db-queries-del.js +0 -141
- package/lib/db-queries-events.js +0 -68
- package/lib/db-queries-import.js +0 -133
- package/lib/db-queries-messages.js +0 -102
- package/lib/db-queries-sessions.js +0 -112
- package/lib/db-queries-streams.js +0 -100
- package/lib/db-queries.js +0 -89
- package/lib/jsonl-parser.js +0 -190
- package/lib/jsonl-watcher.js +0 -64
- package/lib/routes-agent-actions.js +0 -61
- package/lib/routes-auth-config.js +0 -30
- package/lib/routes-conversations.js +0 -96
- package/lib/routes-debug.js +0 -119
- package/lib/routes-messages.js +0 -139
- package/lib/routes-runs.js +0 -156
- package/lib/routes-scripts.js +0 -135
- package/lib/routes-sessions.js +0 -144
- package/lib/routes-threads.js +0 -100
- package/lib/routes-util.js +0 -110
- package/lib/ws-handlers-conv.js +0 -138
- package/lib/ws-handlers-conv2.js +0 -169
- package/lib/ws-handlers-msg.js +0 -121
- package/lib/ws-handlers-queue.js +0 -56
- package/lib/ws-handlers-run.js +0 -182
- package/lib/ws-handlers-scripts.js +0 -66
- package/lib/ws-handlers-session.js +0 -105
- package/lib/ws-handlers-session2.js +0 -85
- package/lib/ws-legacy-handlers.js +0 -51
- package/static/app.js +0 -261
- package/static/css/app-shell.css +0 -419
- package/static/css/brand-bible.css +0 -591
- package/static/css/colors_and_type.css +0 -568
- package/static/css/gmail-skin.css +0 -663
- package/static/css/main.css +0 -4015
- package/static/css/tools-popup.css +0 -472
- package/static/index.html +0 -418
- package/static/js/agent-auth.js +0 -146
- package/static/js/app-shortcuts.js +0 -30
- package/static/js/audio-recorder-processor.js +0 -18
- package/static/js/client-agents.js +0 -155
- package/static/js/client-cache.js +0 -171
- package/static/js/client-conv.js +0 -198
- package/static/js/client-events.js +0 -164
- package/static/js/client-exec.js +0 -160
- package/static/js/client-helpers.js +0 -199
- package/static/js/client-load.js +0 -175
- package/static/js/client-render.js +0 -132
- package/static/js/client-scroll.js +0 -178
- package/static/js/client-status.js +0 -167
- package/static/js/client-streaming.js +0 -117
- package/static/js/client-streaming2.js +0 -116
- package/static/js/client-streaming3.js +0 -153
- package/static/js/client-streaming4.js +0 -194
- package/static/js/client-ui-controls.js +0 -170
- package/static/js/client-ui.js +0 -128
- package/static/js/client-ui2.js +0 -160
- package/static/js/client-url.js +0 -93
- package/static/js/client-utils.js +0 -174
- package/static/js/client-ws-msg.js +0 -88
- package/static/js/client-ws.js +0 -161
- package/static/js/client.js +0 -145
- package/static/js/codec.js +0 -4
- package/static/js/conv-list-machine.js +0 -145
- package/static/js/conv-list-renderer.js +0 -198
- package/static/js/conv-machine.js +0 -110
- package/static/js/conv-sidebar-actions.js +0 -188
- package/static/js/conv-sidebar-clone.js +0 -91
- package/static/js/conversations.js +0 -116
- package/static/js/dialogs-types.js +0 -111
- package/static/js/dialogs.js +0 -53
- package/static/js/event-filter-config.js +0 -36
- package/static/js/event-processor.js +0 -181
- package/static/js/features.js +0 -187
- package/static/js/image-loader-element.js +0 -76
- package/static/js/image-loader.js +0 -146
- package/static/js/prompt-machine.js +0 -108
- package/static/js/recording-machine.js +0 -49
- package/static/js/script-runner.js +0 -192
- package/static/js/state-barrier.js +0 -105
- package/static/js/streaming-renderer-dispatch.js +0 -144
- package/static/js/streaming-renderer-events.js +0 -163
- package/static/js/streaming-renderer-events2.js +0 -125
- package/static/js/streaming-renderer-params.js +0 -38
- package/static/js/streaming-renderer-render-misc.js +0 -107
- package/static/js/streaming-renderer-render.js +0 -181
- package/static/js/streaming-renderer-render2.js +0 -149
- package/static/js/streaming-renderer-render3.js +0 -142
- package/static/js/streaming-renderer-static.js +0 -181
- package/static/js/streaming-renderer-static2.js +0 -140
- package/static/js/streaming-renderer-stream.js +0 -170
- package/static/js/streaming-renderer-text.js +0 -185
- package/static/js/streaming-renderer-tools.js +0 -189
- package/static/js/streaming-renderer-tools2.js +0 -92
- package/static/js/streaming-renderer.js +0 -200
- package/static/js/syntax-highlighter-render.js +0 -72
- package/static/js/syntax-highlighter.js +0 -131
- package/static/js/terminal-machine.js +0 -51
- package/static/js/terminal.js +0 -178
- package/static/js/ui-components-rendering.js +0 -62
- package/static/js/ui-components.js +0 -88
- package/static/js/websocket-manager.js +0 -107
- package/static/js/ws-client.js +0 -87
- package/static/js/ws-core.js +0 -162
- package/static/js/ws-latency.js +0 -88
- package/static/js/ws-machine.js +0 -68
- package/static/lib/msgpackr.min.js +0 -2
- package/static/theme.js +0 -74
- package/static/vendor/highlight-js.css +0 -10
- package/static/vendor/highlight.min.js +0 -1244
- package/static/vendor/prism-dark.css +0 -129
- package/static/vendor/rippleui.css +0 -35
- package/static/vendor/xterm-addon-fit.min.js +0 -8
- package/static/vendor/xterm.css +0 -8
- package/static/vendor/xterm.min.js +0 -8
package/AGENTS.md
CHANGED
|
@@ -1,22 +1,27 @@
|
|
|
1
1
|
# AgentGUI — Agent Notes
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## Architecture (2026-05-19 pivot — single surface)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
One surface. `server.js` serves `site/app/` at `/` and mounts `ccsniff`'s `/v1/history/*` Express router in-process. The legacy `static/` tree and the legacy `lib/routes-*`/`lib/db-queries-*`/`lib/jsonl-watcher.js` modules are gone. `acptoapi` is no longer used by this project.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
- `site/app/index.html` — shell + CSS, imports `anentrypoint-design` from unpkg
|
|
8
|
+
- `site/app/js/backend.js` — same-origin client (`DEFAULT_BACKEND = ''`); `?backend=` query override for cross-origin debugging
|
|
9
|
+
- `site/app/js/app.js` — webjsx view + state, kits-only rendering (PageHeader, SearchInput, TextField, EventList, Panel, Row, Section); exposes `window.__agentgui`
|
|
10
|
+
- `server.js` — boots ACP/agents/websocket plugins, mounts `createHistoryRouter()` from `ccsniff` at `/`, serves `site/app/` as static root
|
|
11
|
+
- Plugins kept (lib/plugins/): acp, agents, database, files, stream, websocket, workflow
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Dependencies:
|
|
14
|
+
- `ccsniff` (>=1.1.0) — exports `createHistoryRouter({projectsDir})` mountable on Express; serves `/v1/history/{sessions,sessions/:sid/events,search,snapshot,reindex,stream}`. Reads `~/.claude/projects` (override via `CLAUDE_PROJECTS_DIR`).
|
|
15
|
+
- `anentrypoint-design` (>=0.0.119) — kit library, single-file ESM from unpkg
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
- `acptoapi` provides chat / messages / models endpoints (existing) + new history endpoints (`/v1/history/sessions`, `/v1/history/sessions/:sid/events`, `/v1/history/search`, `/v1/history/stream`) — see `c:\dev\acptoapi\lib\history\` (ccsniff functionality merged in 2026-05-02).
|
|
17
|
-
- `anentrypoint-design` provides AppShell / Chat / FileGrid / etc. — single-file ESM from unpkg, no install.
|
|
17
|
+
## Browser Witness (2026-05-19)
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
Local server on PORT=3056 (default), `bun server.js`:
|
|
20
|
+
- `GET /health` → 200 JSON
|
|
21
|
+
- `GET /v1/history/sessions` → `{"sessions":[]}` from ccsniff
|
|
22
|
+
- `GET /` → site/app/index.html
|
|
23
|
+
- WS `/sync` → opens, sync_connected
|
|
24
|
+
- Browser at `localhost:3056/`: AppShell renders, nav=[chat,history,settings], SSE `hello` received (live.connected=true, eventCount=1), 0 console errors, backend resolves to `''` (same origin).
|
|
20
25
|
|
|
21
26
|
## Learning audit
|
|
22
27
|
|
package/database.js
CHANGED
|
@@ -5,7 +5,36 @@ import { createRequire } from 'module';
|
|
|
5
5
|
import { initSchema } from './database-schema.js';
|
|
6
6
|
import { migrateFromJson, migrateToACP, migrateConversationColumns } from './database-migrations.js';
|
|
7
7
|
import { migrateACPSchema, migrateBackfillMessages, migrateFTS, migrateAutoVacuum } from './database-migrations-acp.js';
|
|
8
|
-
|
|
8
|
+
// db-queries layer removed; queries is now a no-op proxy. History is served by ccsniff.
|
|
9
|
+
function createQueries(db) {
|
|
10
|
+
const noop = () => undefined;
|
|
11
|
+
const target = {
|
|
12
|
+
_db: db,
|
|
13
|
+
cleanup: noop,
|
|
14
|
+
cleanupEmptyConversations: () => 0,
|
|
15
|
+
cleanupOrphanedSessions: () => 0,
|
|
16
|
+
clearAllStreamingFlags: () => 0,
|
|
17
|
+
getStreamingConversations: () => [],
|
|
18
|
+
getResumableConversations: () => [],
|
|
19
|
+
getActiveSessions: () => [],
|
|
20
|
+
getSessionsProcessingLongerThan: () => [],
|
|
21
|
+
getConversationsList: () => [],
|
|
22
|
+
getConversation: () => null,
|
|
23
|
+
getSession: () => null,
|
|
24
|
+
getLatestSession: () => null,
|
|
25
|
+
getAllSessions: () => [],
|
|
26
|
+
getStreamChunks: () => [],
|
|
27
|
+
getExecutionEvents: () => [],
|
|
28
|
+
searchAgents: () => [],
|
|
29
|
+
};
|
|
30
|
+
return new Proxy(target, {
|
|
31
|
+
get(t, k) {
|
|
32
|
+
if (k in t) return t[k];
|
|
33
|
+
if (typeof k === 'symbol') return undefined;
|
|
34
|
+
return () => undefined;
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
}
|
|
9
38
|
|
|
10
39
|
const require = createRequire(import.meta.url);
|
|
11
40
|
|
|
@@ -75,6 +104,6 @@ function generateId(prefix) {
|
|
|
75
104
|
return `${prefix}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
76
105
|
}
|
|
77
106
|
|
|
78
|
-
export const queries = createQueries(db
|
|
107
|
+
export const queries = createQueries(db);
|
|
79
108
|
|
|
80
109
|
export default { queries };
|
package/lib/http-handler.js
CHANGED
|
@@ -33,7 +33,7 @@ export function createHttpHandler({ BASE_URL, expressApp, queries, sendJSON, ser
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
const pathOnly = req.url.split('?')[0];
|
|
36
|
-
if (pathOnly.startsWith(BASE_URL + '/api/upload/') || pathOnly.startsWith(BASE_URL + '/files/')) return expressApp(req, res);
|
|
36
|
+
if (pathOnly.startsWith(BASE_URL + '/api/upload/') || pathOnly.startsWith(BASE_URL + '/files/') || pathOnly.startsWith('/v1/history')) return expressApp(req, res);
|
|
37
37
|
|
|
38
38
|
if (req.url === '/favicon.ico' || req.url === BASE_URL + '/favicon.ico') {
|
|
39
39
|
const svg = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><rect width="100" height="100" rx="20" fill="#3b82f6"/><text x="50" y="68" font-size="50" font-family="sans-serif" font-weight="bold" fill="white" text-anchor="middle">G</text></svg>';
|
|
@@ -41,13 +41,14 @@ export function createHttpHandler({ BASE_URL, expressApp, queries, sendJSON, ser
|
|
|
41
41
|
res.end(svg); return;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
// serve index.html at root directly (no redirect)
|
|
45
45
|
|
|
46
46
|
let routePath = req.url;
|
|
47
47
|
if (req.url.startsWith(BASE_URL + '/')) { routePath = req.url.slice(BASE_URL.length); }
|
|
48
48
|
else if (req.url === BASE_URL) { routePath = '/'; }
|
|
49
49
|
else if (req.url.startsWith('/api/') || req.url.startsWith('/js/') || req.url.startsWith('/css/') ||
|
|
50
50
|
req.url.startsWith('/vendor/') || req.url.startsWith('/sync') || req.url === '/' ||
|
|
51
|
+
req.url === '/health' || req.url.startsWith('/v1/') ||
|
|
51
52
|
req.url.startsWith('/conversations/')) { routePath = req.url; }
|
|
52
53
|
else { res.writeHead(404); res.end('Not found'); return; }
|
|
53
54
|
|
|
@@ -56,7 +57,7 @@ export function createHttpHandler({ BASE_URL, expressApp, queries, sendJSON, ser
|
|
|
56
57
|
try {
|
|
57
58
|
const pathOnly = routePath.split('?')[0];
|
|
58
59
|
|
|
59
|
-
if (pathOnly === '/api/health' && req.method === 'GET') {
|
|
60
|
+
if ((pathOnly === '/api/health' || pathOnly === '/health') && req.method === 'GET') {
|
|
60
61
|
let dbStatus = { ok: true };
|
|
61
62
|
try { queries._db.prepare('SELECT 1').get(); } catch (e) { dbStatus = { ok: false, error: e.message }; }
|
|
62
63
|
const queueSizes = {};
|
|
@@ -65,28 +66,13 @@ export function createHttpHandler({ BASE_URL, expressApp, queries, sendJSON, ser
|
|
|
65
66
|
return;
|
|
66
67
|
}
|
|
67
68
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
if (scriptsHandler) { await scriptsHandler(req, res); return; }
|
|
76
|
-
const runsHandler = routes.runs._match(req.method, pathOnly);
|
|
77
|
-
if (runsHandler) { await runsHandler(req, res); return; }
|
|
78
|
-
const agentHandler = routes.agents._match(req.method, pathOnly);
|
|
79
|
-
if (agentHandler) { await agentHandler(req, res); return; }
|
|
80
|
-
const agentActionsHandler = routes.agentActions._match(req.method, pathOnly);
|
|
81
|
-
if (agentActionsHandler) { await agentActionsHandler(req, res); return; }
|
|
82
|
-
const authConfigHandler = routes.authConfig._match(req.method, pathOnly);
|
|
83
|
-
if (authConfigHandler) { await authConfigHandler(req, res); return; }
|
|
84
|
-
const utilHandler = routes.util._match(req.method, pathOnly);
|
|
85
|
-
if (utilHandler) { await utilHandler(req, res); return; }
|
|
86
|
-
const threadHandler = routes.threads._match(req.method, pathOnly);
|
|
87
|
-
if (threadHandler) { await threadHandler(req, res); return; }
|
|
88
|
-
const debugHandler = routes.debug._match(req.method, pathOnly);
|
|
89
|
-
if (debugHandler) { await debugHandler(req, res); return; }
|
|
69
|
+
// Legacy REST handlers removed. History served by ccsniff at /v1/history/*.
|
|
70
|
+
for (const key of Object.keys(routes)) {
|
|
71
|
+
try {
|
|
72
|
+
const h = routes[key]?._match?.(req.method, pathOnly);
|
|
73
|
+
if (h) { await h(req, res); return; }
|
|
74
|
+
} catch (_) {}
|
|
75
|
+
}
|
|
90
76
|
if (routePath.startsWith('/api/image/')) {
|
|
91
77
|
const imagePath = routePath.slice('/api/image/'.length);
|
|
92
78
|
const decodedPath = decodeURIComponent(imagePath);
|
package/lib/routes-registry.js
CHANGED
|
@@ -1,50 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import { register as registerConvRoutes } from './routes-conversations.js';
|
|
5
|
-
import { register as registerAgentRoutes } from './routes-agents.js';
|
|
6
|
-
import { register as registerMessagesRoutes } from './routes-messages.js';
|
|
7
|
-
import { register as registerSessionsRoutes } from './routes-sessions.js';
|
|
8
|
-
import { register as registerRunsRoutes } from './routes-runs.js';
|
|
9
|
-
import { register as registerScriptsRoutes } from './routes-scripts.js';
|
|
10
|
-
import { register as registerAgentActionsRoutes } from './routes-agent-actions.js';
|
|
11
|
-
import { register as registerAuthConfigRoutes } from './routes-auth-config.js';
|
|
12
|
-
import { register as registerConvHandlers } from './ws-handlers-conv.js';
|
|
13
|
-
import { register as registerConvHandlers2 } from './ws-handlers-conv2.js';
|
|
14
|
-
import { register as registerSessionHandlers } from './ws-handlers-session.js';
|
|
15
|
-
import { register as registerSessionHandlers2 } from './ws-handlers-session2.js';
|
|
16
|
-
import { register as registerRunHandlers } from './ws-handlers-run.js';
|
|
17
|
-
import { register as registerUtilHandlers } from './ws-handlers-util.js';
|
|
18
|
-
import { register as registerScriptHandlers } from './ws-handlers-scripts.js';
|
|
19
|
-
import { register as registerQueueHandlers } from './ws-handlers-queue.js';
|
|
20
|
-
import { register as registerMsgHandlers } from './ws-handlers-msg.js';
|
|
21
|
-
import { getAgentDescriptor } from './agent-descriptors.js';
|
|
22
|
-
import { getProviderConfigs, saveProviderConfig } from './provider-config.js';
|
|
23
|
-
|
|
1
|
+
// Legacy route/ws registry stripped down. Old REST routes and WS handlers
|
|
2
|
+
// removed in favor of ccsniff /v1/history/* and the static site/app client.
|
|
3
|
+
// Keep as a no-op shim so server.js can still call it.
|
|
24
4
|
export function createRegistry(wsRouter, deps) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
routes.util = registerUtilRoutes({ sendJSON, parseBody, queries, STARTUP_CWD, PKG_VERSION });
|
|
28
|
-
routes.threads = registerThreadRoutes({ sendJSON, parseBody, queries });
|
|
29
|
-
routes.debug = registerDebugRoutes({ sendJSON, queries, activeExecutions, messageQueues, syncClients, wsOptimizer, _errLogPath: errLogPath });
|
|
30
|
-
routes.conv = registerConvRoutes({ sendJSON, parseBody, queries, activeExecutions, broadcastSync });
|
|
31
|
-
routes.agents = registerAgentRoutes({ sendJSON, parseBody, queries, discoveredAgents, getACPStatus, modelCache, getModelsForAgent, debugLog });
|
|
32
|
-
routes.messages = registerMessagesRoutes({ queries, sendJSON, parseBody, broadcastSync, processMessageWithStreaming, activeExecutions, messageQueues, debugLog, logError });
|
|
33
|
-
routes.sessions = registerSessionsRoutes({ queries, sendJSON, activeExecutions, rateLimitState, debugLog });
|
|
34
|
-
routes.runs = registerRunsRoutes({ sendJSON, parseBody, queries, broadcastSync, processMessageWithStreaming, activeExecutions, activeProcessesByRunId, discoveredAgents, STARTUP_CWD });
|
|
35
|
-
routes.scripts = registerScriptsRoutes({ sendJSON, parseBody, queries, broadcastSync, activeScripts, activeExecutions, processMessageWithStreaming, STARTUP_CWD });
|
|
36
|
-
routes.agentActions = registerAgentActionsRoutes({ sendJSON, queries, broadcastSync, discoveredAgents, activeScripts, modelCache, PORT, BASE_URL, rootDir });
|
|
37
|
-
routes.authConfig = registerAuthConfigRoutes({ sendJSON, parseBody, getProviderConfigs, saveProviderConfig });
|
|
38
|
-
|
|
39
|
-
registerConvHandlers(wsRouter, { queries, activeExecutions, rateLimitState, broadcastSync, processMessageWithStreaming, cleanupExecution, getJsonlWatcher });
|
|
40
|
-
registerConvHandlers2(wsRouter, { queries, activeExecutions, rateLimitState, broadcastSync, processMessageWithStreaming, cleanupExecution, getJsonlWatcher });
|
|
41
|
-
registerMsgHandlers(wsRouter, { queries, activeExecutions, messageQueues, broadcastSync, processMessageWithStreaming, logError });
|
|
42
|
-
registerQueueHandlers(wsRouter, { queries, messageQueues, broadcastSync });
|
|
43
|
-
debugLog('[INIT] registerSessionHandlers, agents: ' + discoveredAgents.length);
|
|
44
|
-
registerSessionHandlers(wsRouter, { db: queries, discoveredAgents, modelCache, getAgentDescriptor, activeScripts, broadcastSync });
|
|
45
|
-
registerSessionHandlers2(wsRouter, { discoveredAgents, modelCache, activeScripts, broadcastSync });
|
|
46
|
-
debugLog('[INIT] registerSessionHandlers completed');
|
|
47
|
-
registerRunHandlers(wsRouter, { queries, discoveredAgents, activeExecutions, activeProcessesByRunId, broadcastSync, processMessageWithStreaming, cleanupExecution });
|
|
48
|
-
registerUtilHandlers(wsRouter, { queries, wsOptimizer, broadcastSync, getProviderConfigs, saveProviderConfig, STARTUP_CWD, discoveredAgents });
|
|
49
|
-
registerScriptHandlers(wsRouter, { queries, broadcastSync, STARTUP_CWD, activeScripts });
|
|
5
|
+
// intentionally empty
|
|
50
6
|
}
|
package/lib/server-startup.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
// JsonlWatcher removed; history now served by ccsniff in-process.
|
|
2
|
+
const JsonlWatcher = null;
|
|
2
3
|
|
|
3
4
|
export function createOnServerReady({ queries, broadcastSync, warmAssetCache, staticDir, discoveredAgents, PORT, BASE_URL, watch, setWatcher, resumeInterruptedStreams, activeExecutions, debugLog, installGMAgentConfigs, startACPTools, getACPStatus, execMachine, performAutoImport, performAgentHealthCheck, recoverStaleSessions }) {
|
|
4
5
|
let jsonlWatcher = null;
|
|
@@ -21,16 +22,7 @@ export function createOnServerReady({ queries, broadcastSync, warmAssetCache, st
|
|
|
21
22
|
try { queries.cleanup(); console.log('[cleanup] Scheduled DB cleanup complete'); } catch (e) { console.error('[cleanup] Error:', e.message); }
|
|
22
23
|
}, 6 * 60 * 60 * 1000);
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
console.log('[JSONL] Watcher skipped (AGENTGUI_SKIP_AUTO_IMPORT=1)');
|
|
26
|
-
} else {
|
|
27
|
-
try {
|
|
28
|
-
jsonlWatcher = new JsonlWatcher({ broadcastSync, queries });
|
|
29
|
-
jsonlWatcher.start();
|
|
30
|
-
if (setWatcher) setWatcher(jsonlWatcher);
|
|
31
|
-
console.log('[JSONL] Watcher started');
|
|
32
|
-
} catch (err) { console.error('[JSONL] Watcher failed to start:', err.message); }
|
|
33
|
-
}
|
|
25
|
+
// JsonlWatcher removed; ccsniff handles JSONL history via its own watcher.
|
|
34
26
|
|
|
35
27
|
resumeInterruptedStreams().catch(err => console.error('[RESUME] Startup error:', err.message));
|
|
36
28
|
|
package/lib/ws-setup.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { WebSocketServer } from 'ws';
|
|
4
|
-
|
|
4
|
+
// Legacy WS handlers removed; no-op shim kept for callsite compatibility.
|
|
5
|
+
const registerLegacyHandler = () => {};
|
|
5
6
|
|
|
6
7
|
export function createWsSetup(server, { BASE_URL, watch, staticDir, _assetCache, htmlState, sendWs, wsRouter, debugLog, subscriptionIndex, syncClients, wsOptimizer, legacyDeps }) {
|
|
7
8
|
const hotReloadClients = [];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentgui",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.933",
|
|
4
4
|
"description": "Multi-agent ACP client with real-time communication",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "electron/main.js",
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
"better-sqlite3": "^12.9.0",
|
|
32
32
|
"busboy": "^1.6.0",
|
|
33
33
|
"ccfollow": "^1.0.7",
|
|
34
|
+
"ccsniff": "github:AnEntrypoint/ccsniff#main",
|
|
34
35
|
"execa": "^9.6.1",
|
|
35
36
|
"express": "^5.2.1",
|
|
36
37
|
"form-data": "^4.0.5",
|
|
@@ -48,7 +49,6 @@
|
|
|
48
49
|
},
|
|
49
50
|
"devDependencies": {
|
|
50
51
|
"electron": "^35.0.0",
|
|
51
|
-
"playwright": "^1.59.1"
|
|
52
|
-
"rippleui": "^1.12.1"
|
|
52
|
+
"playwright": "^1.59.1"
|
|
53
53
|
}
|
|
54
54
|
}
|
package/server.js
CHANGED
|
@@ -5,6 +5,7 @@ import { fileURLToPath } from 'url';
|
|
|
5
5
|
import { LRUCache } from 'lru-cache';
|
|
6
6
|
const PKG_VERSION = JSON.parse(fs.readFileSync(new URL('./package.json', import.meta.url), 'utf8')).version;
|
|
7
7
|
import { createExpressApp } from './lib/routes-upload.js';
|
|
8
|
+
import { createHistoryRouter } from 'ccsniff';
|
|
8
9
|
import { queries } from './database.js';
|
|
9
10
|
import { runClaudeWithStreaming } from './lib/claude-runner-run.js';
|
|
10
11
|
import { initializeDescriptors, getAgentDescriptor } from './lib/agent-descriptors.js';
|
|
@@ -64,10 +65,15 @@ const STARTUP_CWD = (() => {
|
|
|
64
65
|
const cwd = process.env.STARTUP_CWD || process.cwd();
|
|
65
66
|
try { fs.accessSync(cwd, fs.constants.R_OK); return cwd; } catch { console.warn(`[server] STARTUP_CWD "${cwd}" not accessible, falling back to ${process.cwd()}`); return process.cwd(); }
|
|
66
67
|
})();
|
|
67
|
-
const staticDir = path.join(rootDir, '
|
|
68
|
+
const staticDir = path.join(rootDir, 'site', 'app');
|
|
68
69
|
if (!fs.existsSync(staticDir)) fs.mkdirSync(staticDir, { recursive: true });
|
|
69
70
|
|
|
70
71
|
const expressApp = createExpressApp({ queries, BASE_URL });
|
|
72
|
+
try {
|
|
73
|
+
const historyRouter = await createHistoryRouter({ projectsDir: process.env.CLAUDE_PROJECTS_DIR });
|
|
74
|
+
expressApp.use('/', historyRouter);
|
|
75
|
+
console.log('[ccsniff] /v1/history/* mounted');
|
|
76
|
+
} catch (e) { console.error('[ccsniff] mount failed:', e.message); }
|
|
71
77
|
|
|
72
78
|
let discoveredAgents = [];
|
|
73
79
|
initializeDescriptors(discoveredAgents);
|
package/site/app/index.html
CHANGED
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
6
6
|
<title>agentgui</title>
|
|
7
7
|
<meta name="description" content="agentgui — live client for any acptoapi backend.">
|
|
8
|
-
<link rel="stylesheet" href="https://unpkg.com/anentrypoint-design@
|
|
8
|
+
<link rel="stylesheet" href="https://unpkg.com/anentrypoint-design@0.0.127/dist/247420.css">
|
|
9
9
|
<script type="importmap">
|
|
10
|
-
{ "imports": { "anentrypoint-design": "https://unpkg.com/anentrypoint-design@
|
|
10
|
+
{ "imports": { "anentrypoint-design": "https://unpkg.com/anentrypoint-design@0.0.127/dist/247420.js" } }
|
|
11
11
|
</script>
|
|
12
12
|
<style>
|
|
13
13
|
html, body { margin: 0; height: 100%; }
|
package/site/app/js/app.js
CHANGED
|
@@ -3,7 +3,7 @@ import * as B from './backend.js';
|
|
|
3
3
|
|
|
4
4
|
installStyles().catch(() => {});
|
|
5
5
|
|
|
6
|
-
const { AppShell, Topbar, Crumb, Side, Status, Chat, ChatComposer, Row, Panel } = C;
|
|
6
|
+
const { AppShell, Topbar, Crumb, Side, Status, Chat, ChatComposer, Row, Panel, PageHeader, SearchInput, TextField, Select, Btn, EventList } = C;
|
|
7
7
|
|
|
8
8
|
const state = {
|
|
9
9
|
backend: B.getBackend(),
|
|
@@ -114,18 +114,16 @@ function view() {
|
|
|
114
114
|
|
|
115
115
|
const crumbRight = state.tab === 'chat'
|
|
116
116
|
? [
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
),
|
|
125
|
-
),
|
|
117
|
+
Select({
|
|
118
|
+
key: 'modelsel',
|
|
119
|
+
value: state.selectedModel,
|
|
120
|
+
placeholder: '— model —',
|
|
121
|
+
options: state.models.map(m => ({ value: m.id, label: m.id })),
|
|
122
|
+
onChange: (v) => { state.selectedModel = v; render(); },
|
|
123
|
+
}),
|
|
126
124
|
state.chat.busy
|
|
127
|
-
?
|
|
128
|
-
:
|
|
125
|
+
? Btn({ key: 'stop', onClick: cancelChat, children: '◼ stop' })
|
|
126
|
+
: Btn({ key: 'new', onClick: newChat, children: '+ new' }),
|
|
129
127
|
dot,
|
|
130
128
|
]
|
|
131
129
|
: [dot];
|
|
@@ -169,13 +167,22 @@ function mainContent() {
|
|
|
169
167
|
|
|
170
168
|
// ── chat ───────────────────────────────────────────────────────────────────
|
|
171
169
|
function chatMain() {
|
|
172
|
-
const
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
170
|
+
const lastIdx = state.chat.messages.length - 1;
|
|
171
|
+
const msgs = state.chat.messages.map((m, i) => {
|
|
172
|
+
const isAssistant = m.role === 'assistant';
|
|
173
|
+
const isStreaming = state.chat.busy && i === lastIdx && isAssistant;
|
|
174
|
+
const isEmptyStreaming = isStreaming && !m.content;
|
|
175
|
+
return {
|
|
176
|
+
key: String(i),
|
|
177
|
+
who: isAssistant ? 'them' : 'you',
|
|
178
|
+
name: isAssistant ? (state.selectedModel || 'agent') : 'you',
|
|
179
|
+
time: m.time || '',
|
|
180
|
+
typing: isEmptyStreaming,
|
|
181
|
+
parts: isEmptyStreaming
|
|
182
|
+
? undefined
|
|
183
|
+
: [{ kind: isAssistant ? 'md' : 'text', text: m.content || '' }],
|
|
184
|
+
};
|
|
185
|
+
});
|
|
179
186
|
|
|
180
187
|
const composer = ChatComposer({
|
|
181
188
|
value: state.chat.draft,
|
|
@@ -235,33 +242,28 @@ async function sendChat() {
|
|
|
235
242
|
|
|
236
243
|
// ── history ────────────────────────────────────────────────────────────────
|
|
237
244
|
function historyMain() {
|
|
238
|
-
const head =
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
state.selectedSid
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
),
|
|
245
|
-
);
|
|
245
|
+
const head = PageHeader({
|
|
246
|
+
title: '§ history',
|
|
247
|
+
lede: state.selectedSid
|
|
248
|
+
? 'session ' + state.selectedSid
|
|
249
|
+
: 'pick a session from the sidebar — events stream from ccsniff /v1/history.',
|
|
250
|
+
});
|
|
246
251
|
|
|
247
252
|
if (!state.selectedSid) return [head];
|
|
248
253
|
if (state.events.length === 0) return [head, Panel({ title: 'events', children: h('p', { class: 'lede' }, '◌ loading…') })];
|
|
249
254
|
|
|
250
|
-
const rows = state.events.map((e, i) =>
|
|
251
|
-
Row({
|
|
252
|
-
key: 'ev' + i,
|
|
253
|
-
rank: String(i + 1).padStart(3, '0'),
|
|
254
|
-
title: (e.text || '').slice(0, 200) || '(empty)',
|
|
255
|
-
sub: new Date(e.ts).toLocaleString() + ' · ' + (e.role || '?') + ' · ' + (e.type || '?') + (e.tool ? ' · ⌘ ' + e.tool : ''),
|
|
256
|
-
rail: e.role === 'error' ? 'flame' : (e.role === 'user' ? 'green' : 'purple'),
|
|
257
|
-
})
|
|
258
|
-
);
|
|
259
|
-
|
|
260
255
|
return [
|
|
261
256
|
head,
|
|
262
257
|
Panel({
|
|
263
258
|
title: state.events.length + ' events',
|
|
264
|
-
children:
|
|
259
|
+
children: EventList({
|
|
260
|
+
items: state.events.map((e, i) => ({
|
|
261
|
+
key: 'ev' + i,
|
|
262
|
+
code: String(i + 1).padStart(3, '0'),
|
|
263
|
+
title: (e.text || '').slice(0, 200) || '(empty)',
|
|
264
|
+
sub: new Date(e.ts).toLocaleString() + ' · ' + (e.role || '?') + ' · ' + (e.type || '?') + (e.tool ? ' · ⌘ ' + e.tool : ''),
|
|
265
|
+
})),
|
|
266
|
+
}),
|
|
265
267
|
}),
|
|
266
268
|
];
|
|
267
269
|
}
|
|
@@ -306,15 +308,15 @@ function historySide() {
|
|
|
306
308
|
}),
|
|
307
309
|
Panel({
|
|
308
310
|
title: searching ? 'matches' : 'sessions',
|
|
309
|
-
children:
|
|
310
|
-
|
|
311
|
-
|
|
311
|
+
children: [
|
|
312
|
+
SearchInput({
|
|
313
|
+
key: 'searchInput',
|
|
312
314
|
placeholder: 'search sessions…',
|
|
313
315
|
value: state.searchQ,
|
|
314
|
-
|
|
316
|
+
onInput: (v) => { state.searchQ = v; runSearch(); },
|
|
315
317
|
}),
|
|
316
|
-
rows.length ? h('div', {}, ...rows) : h('p', { class: 'lede' }, 'no sessions yet'),
|
|
317
|
-
|
|
318
|
+
rows.length ? h('div', { key: 'rows' }, ...rows) : h('p', { key: 'empty', class: 'lede' }, 'no sessions yet'),
|
|
319
|
+
],
|
|
318
320
|
}),
|
|
319
321
|
];
|
|
320
322
|
}
|
|
@@ -323,48 +325,51 @@ function historySide() {
|
|
|
323
325
|
function settingsMain() {
|
|
324
326
|
const ok = state.health.status === 'ok';
|
|
325
327
|
return [
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
328
|
+
PageHeader({
|
|
329
|
+
title: '⌘ settings',
|
|
330
|
+
lede: 'point agentgui at any backend. blank = same-origin (ccsniff in-process). ?backend=… or the field below persists via localStorage.',
|
|
331
|
+
}),
|
|
332
|
+
Panel({
|
|
333
|
+
title: 'backend',
|
|
334
|
+
children: [
|
|
335
|
+
TextField({
|
|
336
|
+
key: 'backendField',
|
|
337
|
+
label: 'backend url',
|
|
338
|
+
value: state.backendDraft,
|
|
339
|
+
placeholder: '(blank = same origin)',
|
|
340
|
+
onInput: (v) => { state.backendDraft = v; render(); },
|
|
341
|
+
}),
|
|
342
|
+
h('p', { key: 'hp', class: 'lede' }, (ok ? '● ' : '○ ') + JSON.stringify(state.health)),
|
|
343
|
+
Btn({
|
|
344
|
+
key: 'savebtn',
|
|
345
|
+
primary: true,
|
|
346
|
+
onClick: (e) => {
|
|
347
|
+
e.preventDefault();
|
|
348
|
+
B.setBackend(state.backendDraft);
|
|
349
|
+
state.backend = state.backendDraft;
|
|
350
|
+
state.health = { status: 'unknown' };
|
|
351
|
+
render();
|
|
352
|
+
init();
|
|
353
|
+
},
|
|
354
|
+
children: 'save + reconnect',
|
|
355
|
+
}),
|
|
356
|
+
],
|
|
357
|
+
}),
|
|
358
|
+
Panel({
|
|
359
|
+
title: 'models',
|
|
360
|
+
children: state.models.length
|
|
361
|
+
? state.models.slice(0, 40).map((m, i) =>
|
|
362
|
+
Row({
|
|
363
|
+
key: 'm' + i,
|
|
364
|
+
rank: String(i + 1).padStart(3, '0'),
|
|
365
|
+
title: m.id,
|
|
366
|
+
sub: m.owned_by || m.object || 'model',
|
|
367
|
+
rail: m.id === state.selectedModel ? 'green' : 'purple',
|
|
368
|
+
onClick: () => { state.selectedModel = m.id; render(); },
|
|
369
|
+
})
|
|
370
|
+
)
|
|
371
|
+
: h('p', { key: 'none', class: 'lede' }, 'no models loaded'),
|
|
372
|
+
}),
|
|
368
373
|
];
|
|
369
374
|
}
|
|
370
375
|
|
package/site/app/js/backend.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// acptoapi backend client. Resolves base URL from ?backend= or localStorage or default.
|
|
2
2
|
const KEY = 'agentgui.backend';
|
|
3
|
-
const DEFAULT_BACKEND = '
|
|
3
|
+
const DEFAULT_BACKEND = '';
|
|
4
4
|
|
|
5
5
|
export function getBackend() {
|
|
6
6
|
const u = new URL(location.href);
|