@evandu/super-pi 0.1.21 → 0.1.23
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/README.md +58 -1
- package/agents/super-pi-memory/index.ts +34 -0
- package/dist/client/assets/index-BKKZnCis.css +1 -0
- package/dist/client/assets/index-LWO_0omC.js +50 -0
- package/dist/client/favicon.ico +0 -0
- package/dist/client/favicon.png +0 -0
- package/dist/client/favicon.svg +10 -0
- package/dist/client/index.html +5 -2
- package/dist/server/active-memory.d.ts +118 -0
- package/dist/server/active-memory.js +214 -0
- package/dist/server/application/conversation-service.js +1 -0
- package/dist/server/application/run-service.d.ts +12 -0
- package/dist/server/application/run-service.js +48 -4
- package/dist/server/command-handler.d.ts +16 -2
- package/dist/server/command-handler.js +24 -2
- package/dist/server/files.d.ts +1 -0
- package/dist/server/files.js +77 -46
- package/dist/server/http-server.d.ts +17 -1
- package/dist/server/http-server.js +185 -20
- package/dist/server/index.js +97 -29
- package/dist/server/memory.d.ts +25 -0
- package/dist/server/memory.js +88 -0
- package/dist/server/persistence/app-state-repository.d.ts +27 -0
- package/dist/server/persistence/app-state-repository.js +1 -0
- package/dist/server/persistence/json-state-repository.d.ts +12 -0
- package/dist/server/persistence/json-state-repository.js +24 -0
- package/dist/server/persistence/open-state-store.d.ts +3 -0
- package/dist/server/persistence/open-state-store.js +35 -0
- package/dist/server/persistence/rename.d.ts +22 -0
- package/dist/server/persistence/rename.js +44 -0
- package/dist/server/persistence/sqlite-state-repository.d.ts +13 -0
- package/dist/server/persistence/sqlite-state-repository.js +114 -0
- package/dist/server/runtime.d.ts +7 -1
- package/dist/server/runtime.js +23 -10
- package/dist/server/server-context.d.ts +12 -0
- package/dist/server/store.d.ts +12 -3
- package/dist/server/store.js +55 -82
- package/dist/server/subagent-runs.d.ts +2 -0
- package/dist/server/subagent-runs.js +6 -0
- package/dist/server/subagents.d.ts +2 -0
- package/dist/server/subagents.js +11 -3
- package/dist/server/terminal.d.ts +139 -0
- package/dist/server/terminal.js +366 -0
- package/dist/server/types.d.ts +69 -2
- package/dist/server/workflow-engine.d.ts +2 -0
- package/dist/server/workflow-engine.js +6 -0
- package/dist/server/ws-server.d.ts +11 -0
- package/dist/server/ws-server.js +42 -2
- package/package.json +2 -129
- package/dist/client/assets/index-B43FWHQ6.js +0 -43
- package/dist/client/assets/index-BY__2nV9.css +0 -1
package/dist/server/ws-server.js
CHANGED
|
@@ -45,12 +45,14 @@ export class WsServer {
|
|
|
45
45
|
catalogService;
|
|
46
46
|
accessToken;
|
|
47
47
|
rootDir;
|
|
48
|
+
onSocketClose;
|
|
48
49
|
constructor(options) {
|
|
49
50
|
this.broadcaster = options.broadcaster;
|
|
50
51
|
this.commandHandler = options.commandHandler;
|
|
51
52
|
this.catalogService = options.catalogService;
|
|
52
53
|
this.accessToken = options.accessToken;
|
|
53
54
|
this.rootDir = options.rootDir;
|
|
55
|
+
this.onSocketClose = options.onSocketClose;
|
|
54
56
|
this.websocketServer = new WebSocketServer({ noServer: true });
|
|
55
57
|
this.setupUpgrade(options.httpServer);
|
|
56
58
|
this.setupConnectionHandling();
|
|
@@ -61,14 +63,45 @@ export class WsServer {
|
|
|
61
63
|
socket.destroy();
|
|
62
64
|
return;
|
|
63
65
|
}
|
|
66
|
+
const origin = request.headers.origin;
|
|
67
|
+
if (origin) {
|
|
68
|
+
try {
|
|
69
|
+
const parsed = new URL(origin);
|
|
70
|
+
const host = request.headers.host;
|
|
71
|
+
if (!host || parsed.host !== host || !["http:", "https:"].includes(parsed.protocol)) {
|
|
72
|
+
socket.destroy();
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
socket.destroy();
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
64
81
|
this.websocketServer.handleUpgrade(request, socket, head, (ws) => {
|
|
65
82
|
this.websocketServer.emit("connection", ws, request);
|
|
66
83
|
});
|
|
67
84
|
});
|
|
68
85
|
}
|
|
69
86
|
setupConnectionHandling() {
|
|
70
|
-
this.websocketServer.on("connection", (socket) => {
|
|
87
|
+
this.websocketServer.on("connection", (socket, request) => {
|
|
71
88
|
this.broadcaster.register(socket);
|
|
89
|
+
/**
|
|
90
|
+
* The peer address, captured ONCE per connection rather than read per message.
|
|
91
|
+
*
|
|
92
|
+
* `socket._socket.remoteAddress` is the real TCP peer, but the terminal re-checks it on every
|
|
93
|
+
* command (`TerminalService.assertUsable`), so it has to be read where the underlying socket is
|
|
94
|
+
* still reachable. Reading it inside the message handler would reach for a private field on a
|
|
95
|
+
* `WebSocket` that may already be torn down, and the terminal is exactly the command family where
|
|
96
|
+
* a missing address must fail CLOSED rather than fall back to "allowed".
|
|
97
|
+
*/
|
|
98
|
+
const remoteAddress = request.socket.remoteAddress;
|
|
99
|
+
/**
|
|
100
|
+
* Terminal session ids this socket has opened. Recorded on `terminal.open` rather than inferred
|
|
101
|
+
* from the service on close, because the service is shared across sockets and a close must kill
|
|
102
|
+
* only the shells belonging to the socket that went away.
|
|
103
|
+
*/
|
|
104
|
+
const terminalSessionIds = new Set();
|
|
72
105
|
socket.send(JSON.stringify({ type: "state", state: this.broadcaster.getStateSnapshot() }));
|
|
73
106
|
if (this.rootDir) {
|
|
74
107
|
socket.send(JSON.stringify({ type: "server.version", version: checkDiskVersion(this.rootDir) }));
|
|
@@ -97,16 +130,23 @@ export class WsServer {
|
|
|
97
130
|
socket.on("close", () => {
|
|
98
131
|
clearInterval(heartbeat);
|
|
99
132
|
this.broadcaster.unregister(socket);
|
|
133
|
+
// Kill the shells this socket started BEFORE clearing the set, so a close that races a final
|
|
134
|
+
// `terminal.open` cannot leak one. The set is per-connection, so another tab's terminal survives.
|
|
135
|
+
if (terminalSessionIds.size)
|
|
136
|
+
this.onSocketClose?.([...terminalSessionIds]);
|
|
137
|
+
terminalSessionIds.clear();
|
|
100
138
|
});
|
|
101
139
|
socket.on("message", async (raw) => {
|
|
102
140
|
let command;
|
|
103
141
|
try {
|
|
104
142
|
command = JSON.parse(raw.toString());
|
|
143
|
+
if (command.type === "terminal.open")
|
|
144
|
+
terminalSessionIds.add(command.sessionId);
|
|
105
145
|
const entityId = await this.commandHandler.handleCommand(command, (event) => {
|
|
106
146
|
if (socket.readyState === WebSocket.OPEN) {
|
|
107
147
|
socket.send(JSON.stringify(event));
|
|
108
148
|
}
|
|
109
|
-
});
|
|
149
|
+
}, remoteAddress);
|
|
110
150
|
if (command.operationRequestId)
|
|
111
151
|
socket.send(JSON.stringify({ type: "operation.result", requestId: command.operationRequestId, ok: true, entityId }));
|
|
112
152
|
}
|
package/package.json
CHANGED
|
@@ -1,129 +1,2 @@
|
|
|
1
|
-
{
|
|
2
|
-
|
|
3
|
-
"version": "0.1.21",
|
|
4
|
-
"description": "Web control plane and companion for Pi",
|
|
5
|
-
"license": "MIT",
|
|
6
|
-
"type": "module",
|
|
7
|
-
"bin": {
|
|
8
|
-
"super-pi": "bin/super-pi.js"
|
|
9
|
-
},
|
|
10
|
-
"pi": {
|
|
11
|
-
"extensions": [
|
|
12
|
-
"./dist/extension.js"
|
|
13
|
-
]
|
|
14
|
-
},
|
|
15
|
-
"files": [
|
|
16
|
-
"dist",
|
|
17
|
-
"agents",
|
|
18
|
-
"bin",
|
|
19
|
-
"README.md"
|
|
20
|
-
],
|
|
21
|
-
"engines": {
|
|
22
|
-
"node": ">=22.19.0"
|
|
23
|
-
},
|
|
24
|
-
"scripts": {
|
|
25
|
-
"prepack": "npm run build",
|
|
26
|
-
"dev": "concurrently --kill-others-on-fail \"npm:dev:server\" \"npm:dev:client\"",
|
|
27
|
-
"dev:client": "vite --host 0.0.0.0",
|
|
28
|
-
"dev:server": "tsx watch src/server/index.ts",
|
|
29
|
-
"build": "tsc -b && vite build",
|
|
30
|
-
"start": "node dist/server/index.js",
|
|
31
|
-
"restart:server": "node scripts/restart-server.mjs",
|
|
32
|
-
"smoke": "npm run build && node scripts/smoke.mjs",
|
|
33
|
-
"check": "node scripts/run-check.mjs"
|
|
34
|
-
},
|
|
35
|
-
"check:logic": [
|
|
36
|
-
"scripts/dispatch-ancestry.test.mjs",
|
|
37
|
-
"scripts/dispatch-endpoint.test.mjs",
|
|
38
|
-
"scripts/dispatched-by.test.mjs",
|
|
39
|
-
"scripts/verify-source-text.test.mjs",
|
|
40
|
-
"scripts/runtime-extension-ui.test.mjs",
|
|
41
|
-
"scripts/agent-mechanism.test.mjs",
|
|
42
|
-
"scripts/agent-wiring.test.mjs",
|
|
43
|
-
"scripts/message-timestamps.test.mjs",
|
|
44
|
-
"scripts/pi-resolution.test.mjs",
|
|
45
|
-
"scripts/agent-real-pi.test.mjs",
|
|
46
|
-
"scripts/image-input-real-pi.test.mjs",
|
|
47
|
-
"scripts/image-upload.test.mjs",
|
|
48
|
-
"scripts/extension-ui-e2e.test.mjs",
|
|
49
|
-
"scripts/session-picker.test.mjs",
|
|
50
|
-
"scripts/workspace-cwd.test.mjs",
|
|
51
|
-
"scripts/subagents.test.mjs",
|
|
52
|
-
"scripts/subagent-noise.test.mjs",
|
|
53
|
-
"scripts/subagent-runs.test.mjs",
|
|
54
|
-
"scripts/conversation-reconcile.test.mjs",
|
|
55
|
-
"scripts/subagent-dispatch.test.mjs",
|
|
56
|
-
"scripts/workflow-plan.test.mjs",
|
|
57
|
-
"scripts/workflow-engine.test.mjs",
|
|
58
|
-
"scripts/workflow-endpoint.test.mjs",
|
|
59
|
-
"scripts/workflow-ui.test.mjs",
|
|
60
|
-
"scripts/agent-vis-records.test.mjs",
|
|
61
|
-
"scripts/queue-store.test.mjs",
|
|
62
|
-
"scripts/followup.test.mjs",
|
|
63
|
-
"scripts/md-render.test.mjs",
|
|
64
|
-
"scripts/revert-session-format.test.mjs",
|
|
65
|
-
"scripts/revert-session-file.test.mjs",
|
|
66
|
-
"scripts/revert-real-pi.test.mjs",
|
|
67
|
-
"scripts/revert-browser.test.mjs",
|
|
68
|
-
"scripts/bg-task.test.mjs",
|
|
69
|
-
"scripts/todo-tool.test.mjs",
|
|
70
|
-
"scripts/tool-calls.test.mjs",
|
|
71
|
-
"scripts/files-api.test.mjs",
|
|
72
|
-
"scripts/files-missing-path.test.mjs",
|
|
73
|
-
"scripts/task-tool.test.mjs",
|
|
74
|
-
"scripts/fork-server.test.mjs",
|
|
75
|
-
"scripts/styles-no-dangling.test.mjs",
|
|
76
|
-
"scripts/theme-no-hardcoded-colours.test.mjs",
|
|
77
|
-
"scripts/agent-config-regression.test.mjs",
|
|
78
|
-
"scripts/model-filter.test.mjs"
|
|
79
|
-
],
|
|
80
|
-
"check:browser": [
|
|
81
|
-
"scripts/extension-ui-browser.test.mjs",
|
|
82
|
-
"scripts/inline-rename-blur.test.mjs",
|
|
83
|
-
"scripts/message-timestamps-browser.test.mjs",
|
|
84
|
-
"scripts/session-picker-browser.test.mjs",
|
|
85
|
-
"scripts/workspace-settings-browser.test.mjs",
|
|
86
|
-
"scripts/subagent-card-browser.test.mjs",
|
|
87
|
-
"scripts/workflow-browser.test.mjs",
|
|
88
|
-
"scripts/conversation-reconcile-browser.test.mjs",
|
|
89
|
-
"scripts/visual-defects-browser.test.mjs",
|
|
90
|
-
"scripts/agent-vis-card-browser.test.mjs",
|
|
91
|
-
"scripts/queue-dock.test.mjs",
|
|
92
|
-
"scripts/md-render-browser.test.mjs",
|
|
93
|
-
"scripts/right-sidebar-browser.test.mjs",
|
|
94
|
-
"scripts/sidebar-tools-browser.test.mjs",
|
|
95
|
-
"scripts/tool-call-blocks-browser.test.mjs",
|
|
96
|
-
"scripts/files-tab-browser.test.mjs",
|
|
97
|
-
"scripts/msg-tabs-browser.test.mjs",
|
|
98
|
-
"scripts/tabs-on-top-browser.test.mjs",
|
|
99
|
-
"scripts/subagent-source.test.mjs",
|
|
100
|
-
"scripts/fork-resize-browser.test.mjs",
|
|
101
|
-
"scripts/msg-bubbles.test.mjs",
|
|
102
|
-
"scripts/narrow-layout.test.mjs",
|
|
103
|
-
"scripts/scrollbar-style.test.mjs",
|
|
104
|
-
"scripts/theme-contrast.test.mjs",
|
|
105
|
-
"scripts/theme-switch-state.test.mjs",
|
|
106
|
-
"scripts/settings-window-structure.test.mjs",
|
|
107
|
-
"scripts/file-tab-selected-contrast.test.mjs",
|
|
108
|
-
"scripts/help-window.test.mjs",
|
|
109
|
-
"scripts/composer-regression-browser.test.mjs",
|
|
110
|
-
"scripts/workspace-picker-browser.test.mjs",
|
|
111
|
-
"scripts/optimistic-browser.test.mjs"
|
|
112
|
-
],
|
|
113
|
-
"dependencies": {
|
|
114
|
-
"ws": "latest"
|
|
115
|
-
},
|
|
116
|
-
"devDependencies": {
|
|
117
|
-
"@types/node": "latest",
|
|
118
|
-
"@types/react": "latest",
|
|
119
|
-
"@types/react-dom": "latest",
|
|
120
|
-
"@types/ws": "latest",
|
|
121
|
-
"@vitejs/plugin-react": "latest",
|
|
122
|
-
"concurrently": "latest",
|
|
123
|
-
"react": "latest",
|
|
124
|
-
"react-dom": "latest",
|
|
125
|
-
"tsx": "latest",
|
|
126
|
-
"typescript": "latest",
|
|
127
|
-
"vite": "latest"
|
|
128
|
-
}
|
|
129
|
-
}
|
|
1
|
+
{ "name": "@evandu/super-pi", "version": "0.1.23", "description": "Web control plane and companion for Pi", "license": "MIT", "type": "module", "bin": { "super-pi": "bin/super-pi.js" }, "pi": { "extensions": [ "./dist/extension.js" ] }, "files": [ "dist", "agents", "bin", "README.md" ], "engines": { "node": ">=22.19.0" }, "scripts": { "prepack": "npm run build", "dev": "concurrently --kill-others-on-fail \"npm:dev:server\" \"npm:dev:client\"", "dev:client": "vite --host 0.0.0.0", "dev:server": "tsx watch src/server/index.ts", "build": "tsc -b && vite build", "start": "node dist/server/index.js", "restart:server": "node scripts/restart-server.mjs", "smoke": "npm run build && node scripts/smoke.mjs", "check": "node scripts/run-check.mjs" }, "check:logic": [ "scripts/lan-access.test.mjs", "scripts/terminal-pty.test.mjs", "scripts/persistence-repository.test.mjs", "scripts/sqlite-repository.test.mjs", "scripts/dispatch-ancestry.test.mjs", "scripts/dispatch-endpoint.test.mjs", "scripts/dispatched-by.test.mjs", "scripts/verify-source-text.test.mjs", "scripts/runtime-extension-ui.test.mjs", "scripts/agent-mechanism.test.mjs", "scripts/agent-wiring.test.mjs", "scripts/message-timestamps.test.mjs", "scripts/pi-resolution.test.mjs", "scripts/agent-real-pi.test.mjs", "scripts/image-input-real-pi.test.mjs", "scripts/image-upload.test.mjs", "scripts/extension-ui-e2e.test.mjs", "scripts/session-picker.test.mjs", "scripts/workspace-cwd.test.mjs", "scripts/subagents.test.mjs", "scripts/subagent-noise.test.mjs", "scripts/subagent-runs.test.mjs", "scripts/conversation-reconcile.test.mjs", "scripts/subagent-dispatch.test.mjs", "scripts/workflow-plan.test.mjs", "scripts/workflow-engine.test.mjs", "scripts/workflow-endpoint.test.mjs", "scripts/workflow-ui.test.mjs", "scripts/agent-vis-records.test.mjs", "scripts/queue-store.test.mjs", "scripts/followup.test.mjs", "scripts/md-render.test.mjs", "scripts/revert-session-format.test.mjs", "scripts/revert-session-file.test.mjs", "scripts/revert-real-pi.test.mjs", "scripts/revert-browser.test.mjs", "scripts/bg-task.test.mjs", "scripts/todo-tool.test.mjs", "scripts/tool-calls.test.mjs", "scripts/files-api.test.mjs", "scripts/files-missing-path.test.mjs", "scripts/task-tool.test.mjs", "scripts/fork-server.test.mjs", "scripts/styles-no-dangling.test.mjs", "scripts/theme-no-hardcoded-colours.test.mjs", "scripts/agent-config-regression.test.mjs", "scripts/model-filter.test.mjs", "scripts/active-memory.test.mjs" ], "check:browser": [ "scripts/extension-ui-browser.test.mjs", "scripts/inline-rename-blur.test.mjs", "scripts/message-timestamps-browser.test.mjs", "scripts/session-picker-browser.test.mjs", "scripts/workspace-settings-browser.test.mjs", "scripts/subagent-card-browser.test.mjs", "scripts/workflow-browser.test.mjs", "scripts/conversation-reconcile-browser.test.mjs", "scripts/visual-defects-browser.test.mjs", "scripts/agent-vis-card-browser.test.mjs", "scripts/queue-dock.test.mjs", "scripts/md-render-browser.test.mjs", "scripts/right-sidebar-browser.test.mjs", "scripts/sidebar-tools-browser.test.mjs", "scripts/tool-call-blocks-browser.test.mjs", "scripts/files-tab-browser.test.mjs", "scripts/msg-tabs-browser.test.mjs", "scripts/tabs-on-top-browser.test.mjs", "scripts/subagent-source.test.mjs", "scripts/fork-resize-browser.test.mjs", "scripts/msg-bubbles.test.mjs", "scripts/narrow-layout.test.mjs", "scripts/scrollbar-style.test.mjs",
|
|
2
|
+
"scripts/stream-tail-browser.test.mjs", "scripts/theme-contrast.test.mjs", "scripts/theme-switch-state.test.mjs", "scripts/settings-window-structure.test.mjs", "scripts/file-tab-selected-contrast.test.mjs", "scripts/help-window.test.mjs", "scripts/composer-regression-browser.test.mjs", "scripts/workspace-picker-browser.test.mjs", "scripts/optimistic-browser.test.mjs", "scripts/active-memory-browser.test.mjs" ], "dependencies": { "ws": "latest" }, "optionalDependencies": { "node-pty": "^1.2.0-beta.15" }, "devDependencies": { "@types/node": "latest", "@types/react": "latest", "@types/react-dom": "latest", "@types/ws": "latest", "@vitejs/plugin-react": "latest", "concurrently": "latest", "react": "latest", "react-dom": "latest", "tsx": "latest", "typescript": "latest", "vite": "latest" } }
|