agentgui 1.0.930 → 1.0.932
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 +35 -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/js/app.js +64 -68
- 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
|
|
|
@@ -114,3 +119,21 @@ bun start was already working (bun has native sqlite support via `bun:sqlite`).
|
|
|
114
119
|
Fix: wrap any bare strings as keyed VElements: `h('span', { key: 'dot' }, '● connected')`. Rule: if ANY sibling in an array has a key, ALL siblings must be VElements (no raw strings or numbers).
|
|
115
120
|
|
|
116
121
|
Surfaced 2026-05-04 while validating the chat surface in `site/app/`. Fix applied to crumbRight construction in `site/app/js/app.js` view().
|
|
122
|
+
|
|
123
|
+
## Live History Stream Wiring (2026-05-05)
|
|
124
|
+
|
|
125
|
+
**`site/app/js/app.js` opens SSE EventSource on navTo('history'); first /v1/history/* request triggers 30-90s loadOnce() synchronous walk.**
|
|
126
|
+
|
|
127
|
+
The live history feature wires acptoapi's /v1/history/stream (SSE endpoint) via `B.streamHistory(base, onEvent)` on tab entry and closes the EventSource on tab exit. State shape: `state.live = { es, connected, lastEventTs, error, eventCount }`.
|
|
128
|
+
|
|
129
|
+
Event dispatch loop:
|
|
130
|
+
- `hello` event: set `connected=true`
|
|
131
|
+
- `event` event: if `data.sid === selectedSid` push into `state.events`, increment matching session counter
|
|
132
|
+
- `conversation` event: call `refreshHistory()` to reload session list
|
|
133
|
+
- `error` event: set `live.error`
|
|
134
|
+
|
|
135
|
+
Throttle renders via `requestAnimationFrame` to avoid event storm during burst loads from acptoapi.
|
|
136
|
+
|
|
137
|
+
**First request to acptoapi /v1/history/* triggers loadOnce() that walks all JSONL files under ~/.claude/projects** (env default; override with `CLAUDE_PROJECTS_DIR`). In our test env: 299 files, 80MB, 69k events → 30-90s startup latency. Health check timeouts during this window are normal and expected. Subsequent requests are fast (cached index).
|
|
138
|
+
|
|
139
|
+
acptoapi binary: `c:/dev/acptoapi/bin/agentapi.js`, default port 4800, no args; CORS `Access-Control-Allow-Origin: *` is enabled.
|
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.932",
|
|
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/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, EventList } = C;
|
|
7
7
|
|
|
8
8
|
const state = {
|
|
9
9
|
backend: B.getBackend(),
|
|
@@ -235,33 +235,29 @@ async function sendChat() {
|
|
|
235
235
|
|
|
236
236
|
// ── history ────────────────────────────────────────────────────────────────
|
|
237
237
|
function historyMain() {
|
|
238
|
-
const head =
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
state.selectedSid
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
),
|
|
245
|
-
);
|
|
238
|
+
const head = PageHeader({
|
|
239
|
+
title: '§ history',
|
|
240
|
+
lede: state.selectedSid
|
|
241
|
+
? 'session ' + state.selectedSid
|
|
242
|
+
: 'pick a session from the sidebar — events stream from ccsniff /v1/history.',
|
|
243
|
+
});
|
|
246
244
|
|
|
247
245
|
if (!state.selectedSid) return [head];
|
|
248
246
|
if (state.events.length === 0) return [head, Panel({ title: 'events', children: h('p', { class: 'lede' }, '◌ loading…') })];
|
|
249
247
|
|
|
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
248
|
return [
|
|
261
249
|
head,
|
|
262
250
|
Panel({
|
|
263
251
|
title: state.events.length + ' events',
|
|
264
|
-
children:
|
|
252
|
+
children: EventList({
|
|
253
|
+
events: state.events.map((e, i) => ({
|
|
254
|
+
key: 'ev' + i,
|
|
255
|
+
rank: String(i + 1).padStart(3, '0'),
|
|
256
|
+
title: (e.text || '').slice(0, 200) || '(empty)',
|
|
257
|
+
sub: new Date(e.ts).toLocaleString() + ' · ' + (e.role || '?') + ' · ' + (e.type || '?') + (e.tool ? ' · ⌘ ' + e.tool : ''),
|
|
258
|
+
rail: e.role === 'error' ? 'flame' : (e.role === 'user' ? 'green' : 'purple'),
|
|
259
|
+
})),
|
|
260
|
+
}),
|
|
265
261
|
}),
|
|
266
262
|
];
|
|
267
263
|
}
|
|
@@ -306,15 +302,15 @@ function historySide() {
|
|
|
306
302
|
}),
|
|
307
303
|
Panel({
|
|
308
304
|
title: searching ? 'matches' : 'sessions',
|
|
309
|
-
children:
|
|
310
|
-
|
|
311
|
-
|
|
305
|
+
children: [
|
|
306
|
+
SearchInput({
|
|
307
|
+
key: 'searchInput',
|
|
312
308
|
placeholder: 'search sessions…',
|
|
313
309
|
value: state.searchQ,
|
|
314
|
-
|
|
310
|
+
onInput: (v) => { state.searchQ = v; runSearch(); },
|
|
315
311
|
}),
|
|
316
|
-
rows.length ? h('div', {}, ...rows) : h('p', { class: 'lede' }, 'no sessions yet'),
|
|
317
|
-
|
|
312
|
+
rows.length ? h('div', { key: 'rows' }, ...rows) : h('p', { key: 'empty', class: 'lede' }, 'no sessions yet'),
|
|
313
|
+
],
|
|
318
314
|
}),
|
|
319
315
|
];
|
|
320
316
|
}
|
|
@@ -323,48 +319,48 @@ function historySide() {
|
|
|
323
319
|
function settingsMain() {
|
|
324
320
|
const ok = state.health.status === 'ok';
|
|
325
321
|
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
|
-
),
|
|
322
|
+
PageHeader({
|
|
323
|
+
title: '⌘ settings',
|
|
324
|
+
lede: 'point agentgui at any backend. blank = same-origin (ccsniff in-process). ?backend=… or the field below persists via localStorage.',
|
|
325
|
+
}),
|
|
326
|
+
Panel({
|
|
327
|
+
title: 'backend',
|
|
328
|
+
children: [
|
|
329
|
+
TextField({
|
|
330
|
+
key: 'backendField',
|
|
331
|
+
label: 'backend url',
|
|
332
|
+
value: state.backendDraft,
|
|
333
|
+
placeholder: '(blank = same origin)',
|
|
334
|
+
onInput: (v) => { state.backendDraft = v; render(); },
|
|
335
|
+
}),
|
|
336
|
+
h('p', { key: 'hp', class: 'lede' }, (ok ? '● ' : '○ ') + JSON.stringify(state.health)),
|
|
337
|
+
h('button', {
|
|
338
|
+
key: 'savebtn',
|
|
339
|
+
onclick: () => {
|
|
340
|
+
B.setBackend(state.backendDraft);
|
|
341
|
+
state.backend = state.backendDraft;
|
|
342
|
+
state.health = { status: 'unknown' };
|
|
343
|
+
render();
|
|
344
|
+
init();
|
|
345
|
+
},
|
|
346
|
+
}, 'save + reconnect'),
|
|
347
|
+
],
|
|
348
|
+
}),
|
|
349
|
+
Panel({
|
|
350
|
+
title: 'models',
|
|
351
|
+
children: state.models.length
|
|
352
|
+
? state.models.slice(0, 40).map((m, i) =>
|
|
353
|
+
Row({
|
|
354
|
+
key: 'm' + i,
|
|
355
|
+
rank: String(i + 1).padStart(3, '0'),
|
|
356
|
+
title: m.id,
|
|
357
|
+
sub: m.owned_by || m.object || 'model',
|
|
358
|
+
rail: m.id === state.selectedModel ? 'green' : 'purple',
|
|
359
|
+
onClick: () => { state.selectedModel = m.id; render(); },
|
|
360
|
+
})
|
|
361
|
+
)
|
|
362
|
+
: h('p', { key: 'none', class: 'lede' }, 'no models loaded'),
|
|
363
|
+
}),
|
|
368
364
|
];
|
|
369
365
|
}
|
|
370
366
|
|
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);
|