@nodetool-ai/websocket 0.7.0-rc.11
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/dist/agent/agent-runtime.d.ts +47 -0
- package/dist/agent/agent-runtime.d.ts.map +1 -0
- package/dist/agent/agent-runtime.js +577 -0
- package/dist/agent/agent-runtime.js.map +1 -0
- package/dist/agent/codex-agent.d.ts +41 -0
- package/dist/agent/codex-agent.d.ts.map +1 -0
- package/dist/agent/codex-agent.js +334 -0
- package/dist/agent/codex-agent.js.map +1 -0
- package/dist/agent/index.d.ts +6 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +4 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/agent/llm-agent.d.ts +51 -0
- package/dist/agent/llm-agent.d.ts.map +1 -0
- package/dist/agent/llm-agent.js +526 -0
- package/dist/agent/llm-agent.js.map +1 -0
- package/dist/agent/mcp-tool-server.d.ts +33 -0
- package/dist/agent/mcp-tool-server.d.ts.map +1 -0
- package/dist/agent/mcp-tool-server.js +292 -0
- package/dist/agent/mcp-tool-server.js.map +1 -0
- package/dist/agent/opencode-agent.d.ts +32 -0
- package/dist/agent/opencode-agent.d.ts.map +1 -0
- package/dist/agent/opencode-agent.js +332 -0
- package/dist/agent/opencode-agent.js.map +1 -0
- package/dist/agent/pi-agent.d.ts +42 -0
- package/dist/agent/pi-agent.d.ts.map +1 -0
- package/dist/agent/pi-agent.js +429 -0
- package/dist/agent/pi-agent.js.map +1 -0
- package/dist/agent/sdk-provider.d.ts +46 -0
- package/dist/agent/sdk-provider.d.ts.map +1 -0
- package/dist/agent/sdk-provider.js +50 -0
- package/dist/agent/sdk-provider.js.map +1 -0
- package/dist/agent/socket-route.d.ts +11 -0
- package/dist/agent/socket-route.d.ts.map +1 -0
- package/dist/agent/socket-route.js +262 -0
- package/dist/agent/socket-route.js.map +1 -0
- package/dist/agent/transport.d.ts +39 -0
- package/dist/agent/transport.d.ts.map +1 -0
- package/dist/agent/transport.js +17 -0
- package/dist/agent/transport.js.map +1 -0
- package/dist/agent/types.d.ts +11 -0
- package/dist/agent/types.d.ts.map +1 -0
- package/dist/agent/types.js +10 -0
- package/dist/agent/types.js.map +1 -0
- package/dist/collection-api.d.ts +14 -0
- package/dist/collection-api.d.ts.map +1 -0
- package/dist/collection-api.js +75 -0
- package/dist/collection-api.js.map +1 -0
- package/dist/error-codes.d.ts +3 -0
- package/dist/error-codes.d.ts.map +1 -0
- package/dist/error-codes.js +2 -0
- package/dist/error-codes.js.map +1 -0
- package/dist/file-api.d.ts +12 -0
- package/dist/file-api.d.ts.map +1 -0
- package/dist/file-api.js +76 -0
- package/dist/file-api.js.map +1 -0
- package/dist/http-api.d.ts +94 -0
- package/dist/http-api.d.ts.map +1 -0
- package/dist/http-api.js +1472 -0
- package/dist/http-api.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/asset-paths.d.ts +10 -0
- package/dist/lib/asset-paths.d.ts.map +1 -0
- package/dist/lib/asset-paths.js +45 -0
- package/dist/lib/asset-paths.js.map +1 -0
- package/dist/lib/bridge.d.ts +8 -0
- package/dist/lib/bridge.d.ts.map +1 -0
- package/dist/lib/bridge.js +70 -0
- package/dist/lib/bridge.js.map +1 -0
- package/dist/mcp-server.d.ts +32 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +842 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/models-api.d.ts +12 -0
- package/dist/models-api.d.ts.map +1 -0
- package/dist/models-api.js +730 -0
- package/dist/models-api.js.map +1 -0
- package/dist/oauth-api.d.ts +28 -0
- package/dist/oauth-api.d.ts.map +1 -0
- package/dist/oauth-api.js +681 -0
- package/dist/oauth-api.js.map +1 -0
- package/dist/openai-api.d.ts +63 -0
- package/dist/openai-api.d.ts.map +1 -0
- package/dist/openai-api.js +359 -0
- package/dist/openai-api.js.map +1 -0
- package/dist/plugins/websocket.d.ts +14 -0
- package/dist/plugins/websocket.d.ts.map +1 -0
- package/dist/plugins/websocket.js +431 -0
- package/dist/plugins/websocket.js.map +1 -0
- package/dist/resolve-media-urls.d.ts +19 -0
- package/dist/resolve-media-urls.d.ts.map +1 -0
- package/dist/resolve-media-urls.js +109 -0
- package/dist/resolve-media-urls.js.map +1 -0
- package/dist/routes/assets.d.ts +22 -0
- package/dist/routes/assets.d.ts.map +1 -0
- package/dist/routes/assets.js +168 -0
- package/dist/routes/assets.js.map +1 -0
- package/dist/routes/collections.d.ts +16 -0
- package/dist/routes/collections.d.ts.map +1 -0
- package/dist/routes/collections.js +32 -0
- package/dist/routes/collections.js.map +1 -0
- package/dist/routes/files.d.ts +12 -0
- package/dist/routes/files.d.ts.map +1 -0
- package/dist/routes/files.js +11 -0
- package/dist/routes/files.js.map +1 -0
- package/dist/routes/health.d.ts +4 -0
- package/dist/routes/health.d.ts.map +1 -0
- package/dist/routes/health.js +41 -0
- package/dist/routes/health.js.map +1 -0
- package/dist/routes/jobs.d.ts +16 -0
- package/dist/routes/jobs.d.ts.map +1 -0
- package/dist/routes/jobs.js +25 -0
- package/dist/routes/jobs.js.map +1 -0
- package/dist/routes/nodes.d.ts +8 -0
- package/dist/routes/nodes.d.ts.map +1 -0
- package/dist/routes/nodes.js +124 -0
- package/dist/routes/nodes.js.map +1 -0
- package/dist/routes/oauth.d.ts +8 -0
- package/dist/routes/oauth.d.ts.map +1 -0
- package/dist/routes/oauth.js +19 -0
- package/dist/routes/oauth.js.map +1 -0
- package/dist/routes/openai.d.ts +8 -0
- package/dist/routes/openai.d.ts.map +1 -0
- package/dist/routes/openai.js +20 -0
- package/dist/routes/openai.js.map +1 -0
- package/dist/routes/storage.d.ts +12 -0
- package/dist/routes/storage.d.ts.map +1 -0
- package/dist/routes/storage.js +13 -0
- package/dist/routes/storage.js.map +1 -0
- package/dist/routes/workflows.d.ts +18 -0
- package/dist/routes/workflows.d.ts.map +1 -0
- package/dist/routes/workflows.js +25 -0
- package/dist/routes/workflows.js.map +1 -0
- package/dist/routes/workspace.d.ts +15 -0
- package/dist/routes/workspace.d.ts.map +1 -0
- package/dist/routes/workspace.js +24 -0
- package/dist/routes/workspace.js.map +1 -0
- package/dist/screenshot-server.d.ts +21 -0
- package/dist/screenshot-server.d.ts.map +1 -0
- package/dist/screenshot-server.js +222 -0
- package/dist/screenshot-server.js.map +1 -0
- package/dist/server.d.ts +10 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +783 -0
- package/dist/server.js.map +1 -0
- package/dist/settings-registry.d.ts +29 -0
- package/dist/settings-registry.d.ts.map +1 -0
- package/dist/settings-registry.js +117 -0
- package/dist/settings-registry.js.map +1 -0
- package/dist/storage-api.d.ts +5 -0
- package/dist/storage-api.d.ts.map +1 -0
- package/dist/storage-api.js +221 -0
- package/dist/storage-api.js.map +1 -0
- package/dist/test-ui-server.d.ts +19 -0
- package/dist/test-ui-server.d.ts.map +1 -0
- package/dist/test-ui-server.js +1256 -0
- package/dist/test-ui-server.js.map +1 -0
- package/dist/trpc/context.d.ts +21 -0
- package/dist/trpc/context.d.ts.map +1 -0
- package/dist/trpc/context.js +10 -0
- package/dist/trpc/context.js.map +1 -0
- package/dist/trpc/error-formatter.d.ts +18 -0
- package/dist/trpc/error-formatter.d.ts.map +1 -0
- package/dist/trpc/error-formatter.js +41 -0
- package/dist/trpc/error-formatter.js.map +1 -0
- package/dist/trpc/index.d.ts +18 -0
- package/dist/trpc/index.d.ts.map +1 -0
- package/dist/trpc/index.js +13 -0
- package/dist/trpc/index.js.map +1 -0
- package/dist/trpc/middleware.d.ts +8 -0
- package/dist/trpc/middleware.d.ts.map +1 -0
- package/dist/trpc/middleware.js +12 -0
- package/dist/trpc/middleware.js.map +1 -0
- package/dist/trpc/router.d.ts +2543 -0
- package/dist/trpc/router.d.ts.map +1 -0
- package/dist/trpc/router.js +43 -0
- package/dist/trpc/router.js.map +1 -0
- package/dist/trpc/routers/assets.d.ts +229 -0
- package/dist/trpc/routers/assets.d.ts.map +1 -0
- package/dist/trpc/routers/assets.js +263 -0
- package/dist/trpc/routers/assets.js.map +1 -0
- package/dist/trpc/routers/collections.d.ts +88 -0
- package/dist/trpc/routers/collections.d.ts.map +1 -0
- package/dist/trpc/routers/collections.js +166 -0
- package/dist/trpc/routers/collections.js.map +1 -0
- package/dist/trpc/routers/costs.d.ts +129 -0
- package/dist/trpc/routers/costs.d.ts.map +1 -0
- package/dist/trpc/routers/costs.js +95 -0
- package/dist/trpc/routers/costs.js.map +1 -0
- package/dist/trpc/routers/files.d.ts +34 -0
- package/dist/trpc/routers/files.d.ts.map +1 -0
- package/dist/trpc/routers/files.js +92 -0
- package/dist/trpc/routers/files.js.map +1 -0
- package/dist/trpc/routers/jobs.d.ts +92 -0
- package/dist/trpc/routers/jobs.d.ts.map +1 -0
- package/dist/trpc/routers/jobs.js +100 -0
- package/dist/trpc/routers/jobs.js.map +1 -0
- package/dist/trpc/routers/mcp-config.d.ts +69 -0
- package/dist/trpc/routers/mcp-config.d.ts.map +1 -0
- package/dist/trpc/routers/mcp-config.js +290 -0
- package/dist/trpc/routers/mcp-config.js.map +1 -0
- package/dist/trpc/routers/messages.d.ts +121 -0
- package/dist/trpc/routers/messages.d.ts.map +1 -0
- package/dist/trpc/routers/messages.js +113 -0
- package/dist/trpc/routers/messages.js.map +1 -0
- package/dist/trpc/routers/models.d.ts +748 -0
- package/dist/trpc/routers/models.d.ts.map +1 -0
- package/dist/trpc/routers/models.js +1107 -0
- package/dist/trpc/routers/models.js.map +1 -0
- package/dist/trpc/routers/nodes.d.ts +48 -0
- package/dist/trpc/routers/nodes.d.ts.map +1 -0
- package/dist/trpc/routers/nodes.js +57 -0
- package/dist/trpc/routers/nodes.js.map +1 -0
- package/dist/trpc/routers/sandboxes.d.ts +64 -0
- package/dist/trpc/routers/sandboxes.d.ts.map +1 -0
- package/dist/trpc/routers/sandboxes.js +327 -0
- package/dist/trpc/routers/sandboxes.js.map +1 -0
- package/dist/trpc/routers/settings.d.ts +113 -0
- package/dist/trpc/routers/settings.d.ts.map +1 -0
- package/dist/trpc/routers/settings.js +193 -0
- package/dist/trpc/routers/settings.js.map +1 -0
- package/dist/trpc/routers/skills.d.ts +41 -0
- package/dist/trpc/routers/skills.d.ts.map +1 -0
- package/dist/trpc/routers/skills.js +194 -0
- package/dist/trpc/routers/skills.js.map +1 -0
- package/dist/trpc/routers/storage.d.ts +44 -0
- package/dist/trpc/routers/storage.d.ts.map +1 -0
- package/dist/trpc/routers/storage.js +153 -0
- package/dist/trpc/routers/storage.js.map +1 -0
- package/dist/trpc/routers/threads.d.ts +95 -0
- package/dist/trpc/routers/threads.d.ts.map +1 -0
- package/dist/trpc/routers/threads.js +150 -0
- package/dist/trpc/routers/threads.js.map +1 -0
- package/dist/trpc/routers/users.d.ts +79 -0
- package/dist/trpc/routers/users.d.ts.map +1 -0
- package/dist/trpc/routers/users.js +125 -0
- package/dist/trpc/routers/users.js.map +1 -0
- package/dist/trpc/routers/workflows.d.ts +681 -0
- package/dist/trpc/routers/workflows.d.ts.map +1 -0
- package/dist/trpc/routers/workflows.js +725 -0
- package/dist/trpc/routers/workflows.js.map +1 -0
- package/dist/trpc/routers/workspace.d.ts +127 -0
- package/dist/trpc/routers/workspace.d.ts.map +1 -0
- package/dist/trpc/routers/workspace.js +203 -0
- package/dist/trpc/routers/workspace.js.map +1 -0
- package/dist/unified-websocket-runner.d.ts +280 -0
- package/dist/unified-websocket-runner.d.ts.map +1 -0
- package/dist/unified-websocket-runner.js +3840 -0
- package/dist/unified-websocket-runner.js.map +1 -0
- package/dist/workspace-api.d.ts +14 -0
- package/dist/workspace-api.d.ts.map +1 -0
- package/dist/workspace-api.js +104 -0
- package/dist/workspace-api.js.map +1 -0
- package/dist/ws-adapter.d.ts +25 -0
- package/dist/ws-adapter.d.ts.map +1 -0
- package/dist/ws-adapter.js +63 -0
- package/dist/ws-adapter.js.map +1 -0
- package/package.json +92 -0
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WebSocket route + transport for the agent runtime.
|
|
3
|
+
*
|
|
4
|
+
* Each connection at `/ws/agent` gets its own `AgentSocketTransport` instance
|
|
5
|
+
* that bridges agent-runtime events to the renderer over the socket using
|
|
6
|
+
* the JSON message protocol defined in `./types.ts`.
|
|
7
|
+
*/
|
|
8
|
+
import { randomUUID } from "node:crypto";
|
|
9
|
+
import { createLogger } from "@nodetool-ai/config";
|
|
10
|
+
import { getAgentRuntime } from "./agent-runtime.js";
|
|
11
|
+
import { clearMcpFrontendTransport } from "../mcp-server.js";
|
|
12
|
+
import { validateAgentClientMessage } from "./types.js";
|
|
13
|
+
const log = createLogger("nodetool.websocket.agent.route");
|
|
14
|
+
const TOOLS_RESPONSE_TIMEOUT_MS = 15000;
|
|
15
|
+
class AgentSocketTransport {
|
|
16
|
+
socket;
|
|
17
|
+
alive = true;
|
|
18
|
+
pendingManifest = new Map();
|
|
19
|
+
pendingTools = new Map();
|
|
20
|
+
constructor(socket) {
|
|
21
|
+
this.socket = socket;
|
|
22
|
+
}
|
|
23
|
+
get isAlive() {
|
|
24
|
+
return this.alive && this.socket.readyState === 1;
|
|
25
|
+
}
|
|
26
|
+
send(message) {
|
|
27
|
+
if (!this.isAlive)
|
|
28
|
+
return;
|
|
29
|
+
try {
|
|
30
|
+
this.socket.send(JSON.stringify(message));
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
log.warn(`Failed to send agent message: ${error instanceof Error ? error.message : String(error)}`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
streamMessage(sessionId, message, done) {
|
|
37
|
+
this.send({
|
|
38
|
+
type: "agent_stream_message",
|
|
39
|
+
session_id: sessionId,
|
|
40
|
+
message,
|
|
41
|
+
done,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
requestToolManifest(sessionId) {
|
|
45
|
+
return new Promise((resolve, reject) => {
|
|
46
|
+
const requestId = randomUUID();
|
|
47
|
+
const timer = setTimeout(() => {
|
|
48
|
+
this.pendingManifest.delete(requestId);
|
|
49
|
+
reject(new Error(`Timed out waiting for renderer tool manifest (${TOOLS_RESPONSE_TIMEOUT_MS}ms)`));
|
|
50
|
+
}, TOOLS_RESPONSE_TIMEOUT_MS);
|
|
51
|
+
this.pendingManifest.set(requestId, { resolve, reject, timer });
|
|
52
|
+
this.send({
|
|
53
|
+
type: "tools_manifest_request",
|
|
54
|
+
request_id: requestId,
|
|
55
|
+
session_id: sessionId,
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
executeTool(sessionId, toolCallId, name, args) {
|
|
60
|
+
return new Promise((resolve, reject) => {
|
|
61
|
+
const requestId = randomUUID();
|
|
62
|
+
const timer = setTimeout(() => {
|
|
63
|
+
this.pendingTools.delete(requestId);
|
|
64
|
+
reject(new Error(`Timed out waiting for renderer to execute tool ${name} (${TOOLS_RESPONSE_TIMEOUT_MS}ms)`));
|
|
65
|
+
}, TOOLS_RESPONSE_TIMEOUT_MS);
|
|
66
|
+
this.pendingTools.set(requestId, { resolve, reject, timer });
|
|
67
|
+
this.send({
|
|
68
|
+
type: "tool_call_request",
|
|
69
|
+
request_id: requestId,
|
|
70
|
+
session_id: sessionId,
|
|
71
|
+
tool_call_id: toolCallId,
|
|
72
|
+
name,
|
|
73
|
+
args,
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
abortTools(sessionId) {
|
|
78
|
+
this.send({ type: "tool_call_abort", session_id: sessionId });
|
|
79
|
+
}
|
|
80
|
+
/** Renderer replied to a `tools_manifest_request`. */
|
|
81
|
+
resolveManifest(requestId, manifest) {
|
|
82
|
+
const pending = this.pendingManifest.get(requestId);
|
|
83
|
+
if (!pending)
|
|
84
|
+
return;
|
|
85
|
+
this.pendingManifest.delete(requestId);
|
|
86
|
+
clearTimeout(pending.timer);
|
|
87
|
+
pending.resolve(manifest);
|
|
88
|
+
}
|
|
89
|
+
/** Renderer replied to a `tool_call_request`. */
|
|
90
|
+
resolveTool(requestId, result) {
|
|
91
|
+
const pending = this.pendingTools.get(requestId);
|
|
92
|
+
if (!pending)
|
|
93
|
+
return;
|
|
94
|
+
this.pendingTools.delete(requestId);
|
|
95
|
+
clearTimeout(pending.timer);
|
|
96
|
+
if (result.isError) {
|
|
97
|
+
pending.reject(new Error(result.error ?? "Tool execution failed"));
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
pending.resolve(result.result);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/** Mark the transport as dead and reject all in-flight renderer requests. */
|
|
104
|
+
dispose() {
|
|
105
|
+
this.alive = false;
|
|
106
|
+
const failure = new Error("Renderer disconnected");
|
|
107
|
+
for (const [, pending] of this.pendingManifest) {
|
|
108
|
+
clearTimeout(pending.timer);
|
|
109
|
+
pending.reject(failure);
|
|
110
|
+
}
|
|
111
|
+
this.pendingManifest.clear();
|
|
112
|
+
for (const [, pending] of this.pendingTools) {
|
|
113
|
+
clearTimeout(pending.timer);
|
|
114
|
+
pending.reject(failure);
|
|
115
|
+
}
|
|
116
|
+
this.pendingTools.clear();
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
const agentSocketRoute = async (app) => {
|
|
120
|
+
app.get("/ws/agent", { websocket: true }, (socket, req) => {
|
|
121
|
+
// The global auth preHandler in server.ts populates req.userId — reject
|
|
122
|
+
// the connection if it ever leaks through unauthenticated. Belt and
|
|
123
|
+
// suspenders: defaults like a misconfigured local dev server should
|
|
124
|
+
// never become an unauthenticated agent endpoint.
|
|
125
|
+
const userId = req.userId;
|
|
126
|
+
if (!userId) {
|
|
127
|
+
log.warn("Agent WebSocket connection rejected: no userId on request");
|
|
128
|
+
try {
|
|
129
|
+
socket.close(1008, "Authentication required");
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
// socket may already be closing — best effort
|
|
133
|
+
}
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
const transport = new AgentSocketTransport(socket);
|
|
137
|
+
const runtime = getAgentRuntime();
|
|
138
|
+
log.info(`Agent WebSocket client connected (user ${userId})`);
|
|
139
|
+
const sendResponse = (requestId, data, error) => {
|
|
140
|
+
transport.send({
|
|
141
|
+
type: "response",
|
|
142
|
+
request_id: requestId,
|
|
143
|
+
data,
|
|
144
|
+
error,
|
|
145
|
+
});
|
|
146
|
+
};
|
|
147
|
+
const handleCommand = async (msg) => {
|
|
148
|
+
try {
|
|
149
|
+
switch (msg.command) {
|
|
150
|
+
case "create_session": {
|
|
151
|
+
const sessionId = await runtime.createSession(msg.options, userId);
|
|
152
|
+
sendResponse(msg.request_id, sessionId);
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
case "send_message": {
|
|
156
|
+
// Don't await — runtime streams replies via transport.streamMessage.
|
|
157
|
+
// Fire-and-forget the response so the renderer knows the command was accepted.
|
|
158
|
+
sendResponse(msg.request_id);
|
|
159
|
+
try {
|
|
160
|
+
await runtime.sendMessageStreaming(msg.session_id, msg.message, transport, userId);
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
164
|
+
log.error(`sendMessage failed for ${msg.session_id}: ${message}`);
|
|
165
|
+
transport.streamMessage(msg.session_id, {
|
|
166
|
+
type: "result",
|
|
167
|
+
uuid: randomUUID(),
|
|
168
|
+
session_id: msg.session_id,
|
|
169
|
+
subtype: "error",
|
|
170
|
+
is_error: true,
|
|
171
|
+
errors: [message],
|
|
172
|
+
}, true);
|
|
173
|
+
}
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
case "stop_execution": {
|
|
177
|
+
await runtime.stopExecution(msg.session_id, userId);
|
|
178
|
+
sendResponse(msg.request_id);
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
case "close_session": {
|
|
182
|
+
runtime.closeSession(msg.session_id, userId);
|
|
183
|
+
sendResponse(msg.request_id);
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
case "list_models": {
|
|
187
|
+
const models = await runtime.listModels(msg.options, userId);
|
|
188
|
+
sendResponse(msg.request_id, models);
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
case "list_sessions": {
|
|
192
|
+
const sessions = await runtime.listSessionsForRequest(msg.options, userId);
|
|
193
|
+
sendResponse(msg.request_id, sessions);
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
case "get_session_messages": {
|
|
197
|
+
const messages = await runtime.getSessionMessagesForRequest(msg.options, userId);
|
|
198
|
+
sendResponse(msg.request_id, messages);
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
case "tools_manifest_response": {
|
|
202
|
+
transport.resolveManifest(msg.request_id, msg.manifest);
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
case "tool_call_response": {
|
|
206
|
+
transport.resolveTool(msg.request_id, msg.result);
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
default: {
|
|
210
|
+
const exhaustive = msg;
|
|
211
|
+
log.warn(`Unknown agent command: ${JSON.stringify(exhaustive)}`);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
catch (error) {
|
|
216
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
217
|
+
log.error(`Agent command failed: ${message}`);
|
|
218
|
+
if ("request_id" in msg && typeof msg.request_id === "string") {
|
|
219
|
+
sendResponse(msg.request_id, undefined, message);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
socket.on("message", (raw) => {
|
|
224
|
+
let rawParsed;
|
|
225
|
+
try {
|
|
226
|
+
const text = raw.toString();
|
|
227
|
+
rawParsed = JSON.parse(text);
|
|
228
|
+
}
|
|
229
|
+
catch (error) {
|
|
230
|
+
log.warn(`Failed to parse agent client message: ${error instanceof Error ? error.message : String(error)}`);
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
const validation = validateAgentClientMessage(rawParsed);
|
|
234
|
+
if (!validation.ok) {
|
|
235
|
+
log.warn(`Rejecting malformed agent client message: ${validation.error}`);
|
|
236
|
+
// If the sender provided a request_id, surface the validation error
|
|
237
|
+
// back to them so they can fix the call. Otherwise the message gets
|
|
238
|
+
// dropped silently (which is correct — there's nothing to respond to).
|
|
239
|
+
const maybeRequestId = rawParsed &&
|
|
240
|
+
typeof rawParsed === "object" &&
|
|
241
|
+
typeof rawParsed.request_id === "string"
|
|
242
|
+
? rawParsed.request_id
|
|
243
|
+
: null;
|
|
244
|
+
if (maybeRequestId) {
|
|
245
|
+
sendResponse(maybeRequestId, undefined, validation.error);
|
|
246
|
+
}
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
void handleCommand(validation.value);
|
|
250
|
+
});
|
|
251
|
+
socket.on("close", () => {
|
|
252
|
+
log.info("Agent WebSocket client disconnected");
|
|
253
|
+
transport.dispose();
|
|
254
|
+
clearMcpFrontendTransport(transport);
|
|
255
|
+
});
|
|
256
|
+
socket.on("error", (error) => {
|
|
257
|
+
log.error("Agent WebSocket error", error);
|
|
258
|
+
});
|
|
259
|
+
});
|
|
260
|
+
};
|
|
261
|
+
export default agentSocketRoute;
|
|
262
|
+
//# sourceMappingURL=socket-route.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"socket-route.js","sourceRoot":"","sources":["../../src/agent/socket-route.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AgentTransport — abstract bridge between the agent runtime and a renderer.
|
|
3
|
+
*
|
|
4
|
+
* The agent runtime (Claude/Codex/OpenCode SDKs) needs to:
|
|
5
|
+
* 1. Stream agent messages back to the renderer.
|
|
6
|
+
* 2. Ask the renderer for the available frontend-tool manifest.
|
|
7
|
+
* 3. Ask the renderer to execute a frontend tool and await its result.
|
|
8
|
+
* 4. Tell the renderer to abort any pending tool calls.
|
|
9
|
+
*
|
|
10
|
+
* In the legacy Electron architecture this was done via Electron IPC
|
|
11
|
+
* (`webContents.send` / `ipcMain.on`). The WebSocket-based architecture
|
|
12
|
+
* provides the same operations over a `ws://.../ws/agent` connection.
|
|
13
|
+
*
|
|
14
|
+
* Implementations live next to their transport (see `socketTransport.ts`).
|
|
15
|
+
*/
|
|
16
|
+
import type { AgentMessage, FrontendToolManifest } from "./types.js";
|
|
17
|
+
export interface AgentTransport {
|
|
18
|
+
/**
|
|
19
|
+
* Push a streaming message for `sessionId` to the renderer.
|
|
20
|
+
* `done=true` signals the end of a turn so the renderer can flush state.
|
|
21
|
+
*/
|
|
22
|
+
streamMessage(sessionId: string, message: AgentMessage, done: boolean): void;
|
|
23
|
+
/**
|
|
24
|
+
* Ask the renderer for the current frontend-tool manifest.
|
|
25
|
+
* Resolves with the manifest array (possibly empty if unavailable).
|
|
26
|
+
* Rejects on timeout or transport error.
|
|
27
|
+
*/
|
|
28
|
+
requestToolManifest(sessionId: string): Promise<FrontendToolManifest[]>;
|
|
29
|
+
/**
|
|
30
|
+
* Ask the renderer to execute a frontend tool. Resolves with the tool
|
|
31
|
+
* result, rejects on error or timeout.
|
|
32
|
+
*/
|
|
33
|
+
executeTool(sessionId: string, toolCallId: string, name: string, args: unknown): Promise<unknown>;
|
|
34
|
+
/** Tell the renderer to abort any pending tool calls for the session. */
|
|
35
|
+
abortTools(sessionId: string): void;
|
|
36
|
+
/** True if the underlying transport is still attached. */
|
|
37
|
+
readonly isAlive: boolean;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/agent/transport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAErE,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;IAE7E;;;;OAIG;IACH,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAAC;IAExE;;;OAGG;IACH,WAAW,CACT,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,OAAO,GACZ,OAAO,CAAC,OAAO,CAAC,CAAC;IAEpB,yEAAyE;IACzE,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAEpC,0DAA0D;IAC1D,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AgentTransport — abstract bridge between the agent runtime and a renderer.
|
|
3
|
+
*
|
|
4
|
+
* The agent runtime (Claude/Codex/OpenCode SDKs) needs to:
|
|
5
|
+
* 1. Stream agent messages back to the renderer.
|
|
6
|
+
* 2. Ask the renderer for the available frontend-tool manifest.
|
|
7
|
+
* 3. Ask the renderer to execute a frontend tool and await its result.
|
|
8
|
+
* 4. Tell the renderer to abort any pending tool calls.
|
|
9
|
+
*
|
|
10
|
+
* In the legacy Electron architecture this was done via Electron IPC
|
|
11
|
+
* (`webContents.send` / `ipcMain.on`). The WebSocket-based architecture
|
|
12
|
+
* provides the same operations over a `ws://.../ws/agent` connection.
|
|
13
|
+
*
|
|
14
|
+
* Implementations live next to their transport (see `socketTransport.ts`).
|
|
15
|
+
*/
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=transport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.js","sourceRoot":"","sources":["../../src/agent/transport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent WebSocket protocol types.
|
|
3
|
+
*
|
|
4
|
+
* The canonical definitions live in `@nodetool-ai/protocol` so both server and
|
|
5
|
+
* renderer can import the exact same shapes. This file re-exports them so
|
|
6
|
+
* callers within `@nodetool-ai/websocket` can keep using a single local import
|
|
7
|
+
* path.
|
|
8
|
+
*/
|
|
9
|
+
export type { AgentProvider, AgentModelDescriptor, AgentModelParams, AgentSessionOptions, AgentModelsRequest, AgentListSessionsRequest, AgentSessionInfoEntry, AgentGetSessionMessagesRequest, AgentTranscriptMessage, AgentMessage, FrontendToolManifest, AgentClientMessage, AgentClientCommand, AgentClientPayload, AgentServerMessage, } from "@nodetool-ai/protocol";
|
|
10
|
+
export { validateAgentClientMessage } from "@nodetool-ai/protocol";
|
|
11
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/agent/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,YAAY,EACV,aAAa,EACb,oBAAoB,EACpB,gBAAgB,EAChB,mBAAmB,EACnB,kBAAkB,EAClB,wBAAwB,EACxB,qBAAqB,EACrB,8BAA8B,EAC9B,sBAAsB,EACtB,YAAY,EACZ,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent WebSocket protocol types.
|
|
3
|
+
*
|
|
4
|
+
* The canonical definitions live in `@nodetool-ai/protocol` so both server and
|
|
5
|
+
* renderer can import the exact same shapes. This file re-exports them so
|
|
6
|
+
* callers within `@nodetool-ai/websocket` can keep using a single local import
|
|
7
|
+
* path.
|
|
8
|
+
*/
|
|
9
|
+
export { validateAgentClientMessage } from "@nodetool-ai/protocol";
|
|
10
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/agent/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAoBH,OAAO,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Collection API — REST handler for the multipart file-upload endpoint.
|
|
3
|
+
*
|
|
4
|
+
* `/api/collections/:name/index` stays on REST because tRPC's JSON link does
|
|
5
|
+
* not handle `multipart/form-data` bodies. All CRUD + query endpoints have
|
|
6
|
+
* moved to the tRPC `collections` router.
|
|
7
|
+
*/
|
|
8
|
+
import type { HttpApiOptions } from "./http-api.js";
|
|
9
|
+
/**
|
|
10
|
+
* Handle POST /api/collections/:name/index (multipart/form-data file upload).
|
|
11
|
+
* Returns `null` for any non-matching path so callers can fall through.
|
|
12
|
+
*/
|
|
13
|
+
export declare function handleCollectionRequest(request: Request, pathname: string, _options: HttpApiOptions): Promise<Response | null>;
|
|
14
|
+
//# sourceMappingURL=collection-api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collection-api.d.ts","sourceRoot":"","sources":["../src/collection-api.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAoBpD;;;GAGG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,cAAc,GACvB,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAoD1B"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Collection API — REST handler for the multipart file-upload endpoint.
|
|
3
|
+
*
|
|
4
|
+
* `/api/collections/:name/index` stays on REST because tRPC's JSON link does
|
|
5
|
+
* not handle `multipart/form-data` bodies. All CRUD + query endpoints have
|
|
6
|
+
* moved to the tRPC `collections` router.
|
|
7
|
+
*/
|
|
8
|
+
import { getVecStore, VecNotFoundError, splitDocument } from "@nodetool-ai/vectorstore";
|
|
9
|
+
function jsonResponse(data, status = 200) {
|
|
10
|
+
return new Response(JSON.stringify(data), {
|
|
11
|
+
status,
|
|
12
|
+
headers: { "content-type": "application/json" }
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
function errorResponse(status, detail) {
|
|
16
|
+
return jsonResponse({ detail }, status);
|
|
17
|
+
}
|
|
18
|
+
function normalizePath(pathname) {
|
|
19
|
+
if (pathname.length > 1 && pathname.endsWith("/")) {
|
|
20
|
+
return pathname.slice(0, -1);
|
|
21
|
+
}
|
|
22
|
+
return pathname;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Handle POST /api/collections/:name/index (multipart/form-data file upload).
|
|
26
|
+
* Returns `null` for any non-matching path so callers can fall through.
|
|
27
|
+
*/
|
|
28
|
+
export async function handleCollectionRequest(request, pathname, _options) {
|
|
29
|
+
pathname = normalizePath(pathname);
|
|
30
|
+
const indexMatch = pathname.match(/^\/api\/collections\/([^/]+)\/index$/);
|
|
31
|
+
if (!indexMatch)
|
|
32
|
+
return null;
|
|
33
|
+
if (request.method !== "POST") {
|
|
34
|
+
return errorResponse(405, "Method not allowed");
|
|
35
|
+
}
|
|
36
|
+
const contentType = request.headers.get("content-type") ?? "";
|
|
37
|
+
if (!contentType.includes("multipart/form-data")) {
|
|
38
|
+
return errorResponse(400, "Expected multipart/form-data");
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
const store = await getVecStore();
|
|
42
|
+
const collectionName = decodeURIComponent(indexMatch[1]);
|
|
43
|
+
const collection = await store.getCollection({ name: collectionName });
|
|
44
|
+
const formData = await request.formData();
|
|
45
|
+
const file = formData.get("file");
|
|
46
|
+
if (!file || !(file instanceof File)) {
|
|
47
|
+
return errorResponse(400, "No file provided");
|
|
48
|
+
}
|
|
49
|
+
const text = await file.text();
|
|
50
|
+
const chunks = splitDocument(text, file.name);
|
|
51
|
+
if (chunks.length > 0) {
|
|
52
|
+
await collection.add({
|
|
53
|
+
ids: chunks.map((_, i) => `${file.name}#${i}`),
|
|
54
|
+
documents: chunks.map((c) => c.text),
|
|
55
|
+
metadatas: chunks.map((c) => ({
|
|
56
|
+
source: c.source_id,
|
|
57
|
+
start_index: String(c.start_index)
|
|
58
|
+
}))
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
return jsonResponse({
|
|
62
|
+
path: file.name,
|
|
63
|
+
chunks: chunks.length,
|
|
64
|
+
error: null
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
if (err instanceof VecNotFoundError) {
|
|
69
|
+
return errorResponse(404, "Collection not found");
|
|
70
|
+
}
|
|
71
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
72
|
+
return errorResponse(500, `Vector store error: ${msg}`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=collection-api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collection-api.js","sourceRoot":"","sources":["../src/collection-api.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-codes.d.ts","sourceRoot":"","sources":["../src/error-codes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,qDAAqD,CAAC;AAC7F,YAAY,EAAE,gBAAgB,EAAE,MAAM,qDAAqD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-codes.js","sourceRoot":"","sources":["../src/error-codes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,qDAAqD,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface FileApiOptions {
|
|
2
|
+
/** Root directory for the file browser sandbox. Defaults to user home. */
|
|
3
|
+
rootDir?: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Handle file browser binary download requests.
|
|
7
|
+
* Route: /api/files/download
|
|
8
|
+
*
|
|
9
|
+
* JSON ops (list, info) have moved to the tRPC `files` router.
|
|
10
|
+
*/
|
|
11
|
+
export declare function handleFileRequest(request: Request, options?: FileApiOptions): Promise<Response>;
|
|
12
|
+
//# sourceMappingURL=file-api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-api.d.ts","sourceRoot":"","sources":["../src/file-api.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,cAAc;IAC7B,0EAA0E;IAC1E,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAqDD;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,OAAO,EAChB,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,QAAQ,CAAC,CAmBnB"}
|
package/dist/file-api.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File browser API — T-WS-9 (binary download only).
|
|
3
|
+
*
|
|
4
|
+
* JSON operations (list, info) have been migrated to the tRPC `files` router.
|
|
5
|
+
* This module retains only the binary download endpoint.
|
|
6
|
+
*/
|
|
7
|
+
import * as fs from "node:fs/promises";
|
|
8
|
+
import * as path from "node:path";
|
|
9
|
+
import * as os from "node:os";
|
|
10
|
+
function errorResponse(status, detail) {
|
|
11
|
+
return new Response(JSON.stringify({ detail }), {
|
|
12
|
+
status,
|
|
13
|
+
headers: { "content-type": "application/json" }
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Resolve a user-provided path within the sandbox root.
|
|
18
|
+
* Returns the resolved absolute path, or null if the path escapes the sandbox.
|
|
19
|
+
*/
|
|
20
|
+
function resolveSandboxed(rootDir, userPath) {
|
|
21
|
+
const resolved = path.resolve(rootDir, userPath.startsWith("/") ? "." + userPath : userPath);
|
|
22
|
+
const normalizedRoot = path.resolve(rootDir);
|
|
23
|
+
if (!resolved.startsWith(normalizedRoot + path.sep) &&
|
|
24
|
+
resolved !== normalizedRoot) {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
return resolved;
|
|
28
|
+
}
|
|
29
|
+
async function handleDownload(url, rootDir) {
|
|
30
|
+
const userPath = url.searchParams.get("path");
|
|
31
|
+
if (!userPath)
|
|
32
|
+
return errorResponse(400, "path parameter is required");
|
|
33
|
+
const resolved = resolveSandboxed(rootDir, userPath);
|
|
34
|
+
if (!resolved)
|
|
35
|
+
return errorResponse(403, "Path traversal not allowed");
|
|
36
|
+
try {
|
|
37
|
+
const stat = await fs.stat(resolved);
|
|
38
|
+
if (stat.isDirectory()) {
|
|
39
|
+
return errorResponse(400, "Cannot download a directory");
|
|
40
|
+
}
|
|
41
|
+
const content = await fs.readFile(resolved);
|
|
42
|
+
return new Response(content, {
|
|
43
|
+
status: 200,
|
|
44
|
+
headers: {
|
|
45
|
+
"content-type": "application/octet-stream",
|
|
46
|
+
"content-length": String(content.byteLength)
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return errorResponse(404, "File not found");
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Handle file browser binary download requests.
|
|
56
|
+
* Route: /api/files/download
|
|
57
|
+
*
|
|
58
|
+
* JSON ops (list, info) have moved to the tRPC `files` router.
|
|
59
|
+
*/
|
|
60
|
+
export async function handleFileRequest(request, options = {}) {
|
|
61
|
+
// File browser exposes the local filesystem — disabled in production
|
|
62
|
+
if (process.env["NODETOOL_ENV"] === "production") {
|
|
63
|
+
return errorResponse(403, "File browser is disabled in production");
|
|
64
|
+
}
|
|
65
|
+
if (request.method !== "GET") {
|
|
66
|
+
return errorResponse(405, "Method not allowed");
|
|
67
|
+
}
|
|
68
|
+
const rootDir = options.rootDir ?? os.homedir();
|
|
69
|
+
const url = new URL(request.url);
|
|
70
|
+
const pathname = url.pathname.replace(/\/+$/, "");
|
|
71
|
+
if (pathname === "/api/files/download") {
|
|
72
|
+
return handleDownload(url, rootDir);
|
|
73
|
+
}
|
|
74
|
+
return errorResponse(404, "Not found");
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=file-api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-api.js","sourceRoot":"","sources":["../src/file-api.ts"],"names":[],"mappings":"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"}
|