@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,526 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LlmAgentSdkProvider — runs an in-process LLM as an agent against the same
|
|
3
|
+
* `ui_*` tool surface the Claude/Codex/OpenCode/Pi harnesses use, and the
|
|
4
|
+
* same workflow-builder system prompt.
|
|
5
|
+
*
|
|
6
|
+
* Architecture:
|
|
7
|
+
*
|
|
8
|
+
* AgentPanel (renderer)
|
|
9
|
+
* │
|
|
10
|
+
* └── /ws/agent (AgentSocketTransport)
|
|
11
|
+
* │
|
|
12
|
+
* ├── create_session{ provider:"llm", chatProviderId, model }
|
|
13
|
+
* ├── send_message{ message }
|
|
14
|
+
* │
|
|
15
|
+
* ▼
|
|
16
|
+
* LlmAgentSession.send()
|
|
17
|
+
* │
|
|
18
|
+
* ├── manifest := transport.requestToolManifest(sessionId)
|
|
19
|
+
* ├── tools := manifest.map(UiBridgeTool) (each delegates back to
|
|
20
|
+
* │ transport.executeTool)
|
|
21
|
+
* ├── provider := getProvider(chatProviderId) (anthropic/openai/...)
|
|
22
|
+
* │
|
|
23
|
+
* └── processChat({ provider, model, tools, ... })
|
|
24
|
+
* ├── streams text chunks ──► onMessage(AgentMessage{type:"assistant"})
|
|
25
|
+
* ├── invokes tool ──► UiBridgeTool.process()
|
|
26
|
+
* │ ──► transport.executeTool()
|
|
27
|
+
* │ ──► renderer runs ui_* tool
|
|
28
|
+
* └── returns final assistant text
|
|
29
|
+
*
|
|
30
|
+
* Unlike the harness providers, there is no subprocess and no MCP server
|
|
31
|
+
* here; tool dispatch is direct over the existing AgentTransport.
|
|
32
|
+
*/
|
|
33
|
+
import { randomUUID } from "node:crypto";
|
|
34
|
+
import { processChat } from "@nodetool-ai/chat";
|
|
35
|
+
import { Tool } from "@nodetool-ai/agents";
|
|
36
|
+
import { ProcessingContext, getProvider as getRuntimeProvider, isProviderConfigured, listRegisteredProviderIds, } from "@nodetool-ai/runtime";
|
|
37
|
+
import { Message as DbMessage, Thread as DbThread, } from "@nodetool-ai/models";
|
|
38
|
+
import { createLogger } from "@nodetool-ai/config";
|
|
39
|
+
import { SYSTEM_PROMPT, } from "./sdk-provider.js";
|
|
40
|
+
const log = createLogger("nodetool.websocket.agent.llm");
|
|
41
|
+
const MAX_AGGREGATED_MODELS = 200;
|
|
42
|
+
/**
|
|
43
|
+
* Marker stored on every persisted LLM-agent message so we can list /
|
|
44
|
+
* disambiguate these threads from regular chat threads (which may also
|
|
45
|
+
* carry `agent_mode = true` from the unified-websocket-runner path).
|
|
46
|
+
*/
|
|
47
|
+
const LLM_AGENT_MARKER = "llm-agent";
|
|
48
|
+
/**
|
|
49
|
+
* Wraps a renderer-resident UI tool as an in-process Tool. `process()` proxies
|
|
50
|
+
* the call back over the AgentTransport — same path the MCP server uses for
|
|
51
|
+
* harness providers, but without the MCP indirection.
|
|
52
|
+
*/
|
|
53
|
+
class UiBridgeTool extends Tool {
|
|
54
|
+
transport;
|
|
55
|
+
sessionId;
|
|
56
|
+
name;
|
|
57
|
+
description;
|
|
58
|
+
inputSchema;
|
|
59
|
+
constructor(transport, sessionId, manifest) {
|
|
60
|
+
super();
|
|
61
|
+
this.transport = transport;
|
|
62
|
+
this.sessionId = sessionId;
|
|
63
|
+
this.name = manifest.name;
|
|
64
|
+
this.description = manifest.description;
|
|
65
|
+
// Manifest parameters are already JSON Schema (see toolSchemas.ts and the
|
|
66
|
+
// renderer's frontend tool registration). Pass through unchanged.
|
|
67
|
+
this.inputSchema =
|
|
68
|
+
manifest.parameters ?? {
|
|
69
|
+
type: "object",
|
|
70
|
+
properties: {},
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
async process(_ctx, params) {
|
|
74
|
+
try {
|
|
75
|
+
return await this.transport.executeTool(this.sessionId, randomUUID(), this.name, params);
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
// Tool failures (validation, runtime, etc.) must be returned to the
|
|
79
|
+
// model as a tool-result so it can self-correct on the next turn,
|
|
80
|
+
// matching how harness providers (Claude SDK, MCP) surface errors.
|
|
81
|
+
// Rethrowing here would crash the entire processChat loop and end the
|
|
82
|
+
// session on a single bad call.
|
|
83
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
84
|
+
let argsPreview;
|
|
85
|
+
try {
|
|
86
|
+
argsPreview = JSON.stringify(params);
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
argsPreview = "[unserializable]";
|
|
90
|
+
}
|
|
91
|
+
if (argsPreview.length > 500) {
|
|
92
|
+
argsPreview = argsPreview.slice(0, 497) + "...";
|
|
93
|
+
}
|
|
94
|
+
log.warn(`Tool ${this.name} failed in session ${this.sessionId}: ${message} | args=${argsPreview}`);
|
|
95
|
+
return { isError: true, error: message };
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Convert a persisted `nodetool_messages` row back into the runtime `Message`
|
|
101
|
+
* shape `processChat` consumes. Mirrors the chat handler's
|
|
102
|
+
* `dbMessageToProviderMessage` (kept private there) — duplicated rather than
|
|
103
|
+
* exported because that file is large and the agent runtime should not pull
|
|
104
|
+
* the entire UnifiedWebSocketRunner just to translate three fields.
|
|
105
|
+
*/
|
|
106
|
+
function dbMessageToConversation(m) {
|
|
107
|
+
const role = m.role;
|
|
108
|
+
if (!role || !["user", "assistant", "system", "tool"].includes(role)) {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
const rawContent = Array.isArray(m.content)
|
|
112
|
+
? m.content
|
|
113
|
+
: m.content;
|
|
114
|
+
return {
|
|
115
|
+
role,
|
|
116
|
+
content: rawContent ?? "",
|
|
117
|
+
toolCalls: Array.isArray(m.tool_calls)
|
|
118
|
+
? m.tool_calls
|
|
119
|
+
: null,
|
|
120
|
+
toolCallId: typeof m.tool_call_id === "string" ? m.tool_call_id : null,
|
|
121
|
+
threadId: m.thread_id,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
class LlmAgentSession {
|
|
125
|
+
closed = false;
|
|
126
|
+
inFlight = false;
|
|
127
|
+
abortController = null;
|
|
128
|
+
conversation = [];
|
|
129
|
+
/** Number of `conversation` entries already saved to DB. */
|
|
130
|
+
persistedCount = 0;
|
|
131
|
+
/** True once the persisted history (or system prompt) is loaded. */
|
|
132
|
+
hydrated = false;
|
|
133
|
+
chatProviderId;
|
|
134
|
+
model;
|
|
135
|
+
systemPrompt;
|
|
136
|
+
userId;
|
|
137
|
+
threadId;
|
|
138
|
+
constructor(opts) {
|
|
139
|
+
if (!opts.userId) {
|
|
140
|
+
throw new Error("LlmAgentSession requires an authenticated userId");
|
|
141
|
+
}
|
|
142
|
+
this.chatProviderId = opts.chatProviderId;
|
|
143
|
+
this.model = opts.model;
|
|
144
|
+
this.systemPrompt = opts.systemPrompt ?? SYSTEM_PROMPT;
|
|
145
|
+
this.userId = opts.userId;
|
|
146
|
+
// Lazy: thread row is created on first send so we don't write to the DB
|
|
147
|
+
// for sessions the user opens but never sends a message in.
|
|
148
|
+
this.threadId = opts.threadId ?? "";
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Either load the existing thread's transcript (resume) or insert a fresh
|
|
152
|
+
* thread row (new session). Idempotent — only runs once per session.
|
|
153
|
+
*/
|
|
154
|
+
async hydrate() {
|
|
155
|
+
if (this.hydrated)
|
|
156
|
+
return;
|
|
157
|
+
if (this.threadId) {
|
|
158
|
+
const existing = await DbThread.find(this.userId, this.threadId);
|
|
159
|
+
if (!existing) {
|
|
160
|
+
// Renderer asked to resume a thread we don't own — refuse loudly so
|
|
161
|
+
// the user gets a clear error instead of a phantom new session.
|
|
162
|
+
throw new Error(`Cannot resume LLM agent session: thread ${this.threadId} not found for user ${this.userId}`);
|
|
163
|
+
}
|
|
164
|
+
const [rows] = await DbMessage.paginate(this.threadId, { limit: 1000 });
|
|
165
|
+
for (const row of rows) {
|
|
166
|
+
const msg = dbMessageToConversation(row);
|
|
167
|
+
if (msg)
|
|
168
|
+
this.conversation.push(msg);
|
|
169
|
+
}
|
|
170
|
+
this.persistedCount = this.conversation.length;
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
const thread = await DbThread.create({
|
|
174
|
+
user_id: this.userId,
|
|
175
|
+
title: "",
|
|
176
|
+
});
|
|
177
|
+
this.threadId = thread.id;
|
|
178
|
+
}
|
|
179
|
+
if (this.conversation.length === 0 && this.systemPrompt) {
|
|
180
|
+
// System prompt is part of the conversation but not persisted — it's
|
|
181
|
+
// a server-side configuration concern and doesn't belong in the user's
|
|
182
|
+
// transcript.
|
|
183
|
+
this.conversation.push({
|
|
184
|
+
role: "system",
|
|
185
|
+
content: this.systemPrompt,
|
|
186
|
+
});
|
|
187
|
+
this.persistedCount = this.conversation.length;
|
|
188
|
+
}
|
|
189
|
+
this.hydrated = true;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Persist any messages from `persistedCount` onward. Called after each
|
|
193
|
+
* processChat turn — saves the user message + every assistant / tool
|
|
194
|
+
* message generated this turn, in order.
|
|
195
|
+
*/
|
|
196
|
+
async persistNewMessages() {
|
|
197
|
+
for (let i = this.persistedCount; i < this.conversation.length; i++) {
|
|
198
|
+
const m = this.conversation[i];
|
|
199
|
+
// Skip the system prompt — it's not part of the user-visible transcript.
|
|
200
|
+
if (m.role === "system")
|
|
201
|
+
continue;
|
|
202
|
+
const content = m.content ?? null;
|
|
203
|
+
try {
|
|
204
|
+
await DbMessage.create({
|
|
205
|
+
thread_id: this.threadId,
|
|
206
|
+
user_id: this.userId,
|
|
207
|
+
role: m.role,
|
|
208
|
+
content: typeof content === "string" || content === null
|
|
209
|
+
? content
|
|
210
|
+
: content,
|
|
211
|
+
tool_calls: Array.isArray(m.toolCalls)
|
|
212
|
+
? m.toolCalls
|
|
213
|
+
: null,
|
|
214
|
+
tool_call_id: m.toolCallId ?? null,
|
|
215
|
+
provider: this.chatProviderId,
|
|
216
|
+
model: this.model,
|
|
217
|
+
agent_mode: true,
|
|
218
|
+
agent_execution_id: LLM_AGENT_MARKER,
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
catch (err) {
|
|
222
|
+
log.warn(`Failed to persist LLM agent message (thread ${this.threadId}): ${err instanceof Error ? err.message : String(err)}`);
|
|
223
|
+
// Persistence is best-effort — failing here shouldn't kill the turn.
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
this.persistedCount = this.conversation.length;
|
|
227
|
+
}
|
|
228
|
+
/** Externally observable thread/session id. */
|
|
229
|
+
getThreadId() {
|
|
230
|
+
return this.threadId;
|
|
231
|
+
}
|
|
232
|
+
async send(message, transport, sessionId, manifest, onMessage, _mcpServerUrl) {
|
|
233
|
+
if (this.closed) {
|
|
234
|
+
throw new Error("Cannot send to a closed session");
|
|
235
|
+
}
|
|
236
|
+
if (this.inFlight) {
|
|
237
|
+
throw new Error("A request is already in progress for this session");
|
|
238
|
+
}
|
|
239
|
+
if (!transport) {
|
|
240
|
+
throw new Error("LLM agent session requires an active transport");
|
|
241
|
+
}
|
|
242
|
+
this.inFlight = true;
|
|
243
|
+
this.abortController = new AbortController();
|
|
244
|
+
const out = [];
|
|
245
|
+
const emit = (msg) => {
|
|
246
|
+
out.push(msg);
|
|
247
|
+
onMessage?.(msg);
|
|
248
|
+
};
|
|
249
|
+
try {
|
|
250
|
+
await this.hydrate();
|
|
251
|
+
const provider = await getRuntimeProvider(this.chatProviderId, this.userId);
|
|
252
|
+
const tools = manifest.map((m) => new UiBridgeTool(transport, sessionId, m));
|
|
253
|
+
// ProcessingContext is required by the Tool interface but UiBridgeTool
|
|
254
|
+
// ignores it (the renderer holds all state). A minimal ctx is enough.
|
|
255
|
+
const ctx = new ProcessingContext({
|
|
256
|
+
jobId: `llm-agent-${sessionId}`,
|
|
257
|
+
userId: this.userId,
|
|
258
|
+
});
|
|
259
|
+
let assistantText = "";
|
|
260
|
+
// The renderer dedupes assistant messages by `uuid` and replaces in
|
|
261
|
+
// place (see web/src/stores/AgentStore.ts). To make streaming text
|
|
262
|
+
// appear as a single growing bubble (matching the harness providers),
|
|
263
|
+
// hold a stable uuid for the run of text, send the full accumulated
|
|
264
|
+
// content on every chunk, and reset on each tool call so any text
|
|
265
|
+
// that follows the tool result starts a new bubble.
|
|
266
|
+
let currentTextUuid = null;
|
|
267
|
+
let currentTextBuffer = "";
|
|
268
|
+
await processChat({
|
|
269
|
+
userInput: message,
|
|
270
|
+
messages: this.conversation,
|
|
271
|
+
model: this.model,
|
|
272
|
+
provider,
|
|
273
|
+
context: ctx,
|
|
274
|
+
tools,
|
|
275
|
+
threadId: this.threadId,
|
|
276
|
+
signal: this.abortController.signal,
|
|
277
|
+
callbacks: {
|
|
278
|
+
onChunk: (text) => {
|
|
279
|
+
assistantText += text;
|
|
280
|
+
currentTextBuffer += text;
|
|
281
|
+
if (!currentTextUuid) {
|
|
282
|
+
currentTextUuid = randomUUID();
|
|
283
|
+
}
|
|
284
|
+
emit({
|
|
285
|
+
type: "assistant",
|
|
286
|
+
uuid: currentTextUuid,
|
|
287
|
+
session_id: this.threadId,
|
|
288
|
+
text: currentTextBuffer,
|
|
289
|
+
content: [{ type: "text", text: currentTextBuffer }],
|
|
290
|
+
});
|
|
291
|
+
},
|
|
292
|
+
onToolCall: (toolCall) => {
|
|
293
|
+
currentTextUuid = null;
|
|
294
|
+
currentTextBuffer = "";
|
|
295
|
+
emit({
|
|
296
|
+
type: "assistant",
|
|
297
|
+
uuid: toolCall.id,
|
|
298
|
+
session_id: this.threadId,
|
|
299
|
+
tool_calls: [
|
|
300
|
+
{
|
|
301
|
+
id: toolCall.id,
|
|
302
|
+
type: "function",
|
|
303
|
+
function: {
|
|
304
|
+
name: toolCall.name,
|
|
305
|
+
arguments: JSON.stringify(toolCall.args ?? {}),
|
|
306
|
+
},
|
|
307
|
+
},
|
|
308
|
+
],
|
|
309
|
+
});
|
|
310
|
+
},
|
|
311
|
+
},
|
|
312
|
+
});
|
|
313
|
+
await this.persistNewMessages();
|
|
314
|
+
emit({
|
|
315
|
+
type: "result",
|
|
316
|
+
uuid: randomUUID(),
|
|
317
|
+
session_id: this.threadId,
|
|
318
|
+
text: assistantText,
|
|
319
|
+
is_error: false,
|
|
320
|
+
subtype: "success",
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
catch (error) {
|
|
324
|
+
const errMsg = error instanceof Error ? error.message : String(error);
|
|
325
|
+
log.error(`LLM agent session ${sessionId} failed`, error instanceof Error ? error : new Error(errMsg));
|
|
326
|
+
// Even on failure, save whatever did get appended (e.g. the user message)
|
|
327
|
+
// so the transcript stays consistent across retries.
|
|
328
|
+
try {
|
|
329
|
+
await this.persistNewMessages();
|
|
330
|
+
}
|
|
331
|
+
catch {
|
|
332
|
+
// already logged
|
|
333
|
+
}
|
|
334
|
+
emit({
|
|
335
|
+
type: "result",
|
|
336
|
+
uuid: randomUUID(),
|
|
337
|
+
session_id: this.threadId || sessionId,
|
|
338
|
+
subtype: "error",
|
|
339
|
+
is_error: true,
|
|
340
|
+
errors: [errMsg],
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
finally {
|
|
344
|
+
this.inFlight = false;
|
|
345
|
+
this.abortController = null;
|
|
346
|
+
}
|
|
347
|
+
return out;
|
|
348
|
+
}
|
|
349
|
+
async interrupt() {
|
|
350
|
+
this.abortController?.abort();
|
|
351
|
+
}
|
|
352
|
+
close() {
|
|
353
|
+
if (this.closed)
|
|
354
|
+
return;
|
|
355
|
+
this.closed = true;
|
|
356
|
+
this.abortController?.abort();
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Aggregate language models from every configured chat provider, filter to
|
|
361
|
+
* those that support tool calls, and tag each descriptor with its underlying
|
|
362
|
+
* `chatProviderId`. The renderer surfaces these as a single flat list under
|
|
363
|
+
* the "llm" agent provider.
|
|
364
|
+
*/
|
|
365
|
+
async function listAllToolCapableLanguageModels(userId) {
|
|
366
|
+
const providerIds = listRegisteredProviderIds();
|
|
367
|
+
const out = [];
|
|
368
|
+
for (const providerId of providerIds) {
|
|
369
|
+
if (!(await isProviderConfigured(providerId, userId)))
|
|
370
|
+
continue;
|
|
371
|
+
let provider;
|
|
372
|
+
try {
|
|
373
|
+
provider = await getRuntimeProvider(providerId, userId);
|
|
374
|
+
}
|
|
375
|
+
catch {
|
|
376
|
+
continue;
|
|
377
|
+
}
|
|
378
|
+
let models;
|
|
379
|
+
try {
|
|
380
|
+
models = await provider.getAvailableLanguageModels();
|
|
381
|
+
}
|
|
382
|
+
catch {
|
|
383
|
+
continue;
|
|
384
|
+
}
|
|
385
|
+
if (!models || models.length === 0)
|
|
386
|
+
continue;
|
|
387
|
+
const flags = await Promise.all(models.map((m) => provider
|
|
388
|
+
.hasToolSupport(m.id)
|
|
389
|
+
.catch(() => true)));
|
|
390
|
+
for (let i = 0; i < models.length; i++) {
|
|
391
|
+
if (flags[i] === false)
|
|
392
|
+
continue;
|
|
393
|
+
const m = models[i];
|
|
394
|
+
out.push({
|
|
395
|
+
id: m.id,
|
|
396
|
+
label: `${m.name || m.id} (${providerId})`,
|
|
397
|
+
provider: "llm",
|
|
398
|
+
chatProviderId: providerId,
|
|
399
|
+
});
|
|
400
|
+
if (out.length >= MAX_AGGREGATED_MODELS)
|
|
401
|
+
return out;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
if (out.length > 0) {
|
|
405
|
+
out[0].isDefault = true;
|
|
406
|
+
}
|
|
407
|
+
return out;
|
|
408
|
+
}
|
|
409
|
+
export class LlmAgentSdkProvider {
|
|
410
|
+
name = "llm";
|
|
411
|
+
async listModels(userId, _workspacePath) {
|
|
412
|
+
if (!userId) {
|
|
413
|
+
throw new Error("listModels requires an authenticated userId");
|
|
414
|
+
}
|
|
415
|
+
return listAllToolCapableLanguageModels(userId);
|
|
416
|
+
}
|
|
417
|
+
createSession(options) {
|
|
418
|
+
if (!options.chatProviderId) {
|
|
419
|
+
throw new Error("LLM agent session requires `chatProviderId` (e.g. 'anthropic', 'openai').");
|
|
420
|
+
}
|
|
421
|
+
if (!options.userId) {
|
|
422
|
+
throw new Error("LLM agent session requires an authenticated userId");
|
|
423
|
+
}
|
|
424
|
+
return new LlmAgentSession({
|
|
425
|
+
chatProviderId: options.chatProviderId,
|
|
426
|
+
model: options.model,
|
|
427
|
+
systemPrompt: options.systemPrompt,
|
|
428
|
+
userId: options.userId,
|
|
429
|
+
// The renderer's `resumeSessionId` is our DB thread id — `send()`
|
|
430
|
+
// hydrates from `Message.paginate(threadId)` on first call.
|
|
431
|
+
threadId: options.resumeSessionId,
|
|
432
|
+
});
|
|
433
|
+
}
|
|
434
|
+
async listSessions(options, userId) {
|
|
435
|
+
if (!userId) {
|
|
436
|
+
throw new Error("listSessions requires an authenticated userId");
|
|
437
|
+
}
|
|
438
|
+
// listSessions() in the harness providers returns sessions stored by their
|
|
439
|
+
// SDK (e.g. ~/.claude). For LLM sessions we own the storage — query the
|
|
440
|
+
// `nodetool_messages` table for threads marked with LLM_AGENT_MARKER and
|
|
441
|
+
// hydrate the most recent message of each as a summary.
|
|
442
|
+
try {
|
|
443
|
+
const limit = options.limit ?? 50;
|
|
444
|
+
// Drizzle-ORM access goes through the @nodetool-ai/models package. To keep
|
|
445
|
+
// this provider self-contained, do a paginated thread scan and filter
|
|
446
|
+
// each thread's messages — there are typically O(tens) of threads, so
|
|
447
|
+
// this is fine.
|
|
448
|
+
const [threads] = await DbThread.paginate(userId, { limit: 200 });
|
|
449
|
+
const entries = [];
|
|
450
|
+
for (const thread of threads) {
|
|
451
|
+
const [rows] = await DbMessage.paginate(thread.id, { limit: 1 });
|
|
452
|
+
const first = rows[0];
|
|
453
|
+
if (!first)
|
|
454
|
+
continue;
|
|
455
|
+
if (first.agent_execution_id !== LLM_AGENT_MARKER)
|
|
456
|
+
continue;
|
|
457
|
+
const summary = typeof first.content === "string"
|
|
458
|
+
? first.content.slice(0, 80)
|
|
459
|
+
: thread.title || `Session ${thread.id.slice(0, 8)}`;
|
|
460
|
+
entries.push({
|
|
461
|
+
sessionId: thread.id,
|
|
462
|
+
summary,
|
|
463
|
+
lastModified: Date.parse(thread.updated_at) || Date.now(),
|
|
464
|
+
customTitle: thread.title || undefined,
|
|
465
|
+
firstPrompt: typeof first.content === "string" ? first.content : undefined,
|
|
466
|
+
createdAt: Date.parse(thread.created_at) || undefined,
|
|
467
|
+
provider: "llm",
|
|
468
|
+
});
|
|
469
|
+
if (entries.length >= limit)
|
|
470
|
+
break;
|
|
471
|
+
}
|
|
472
|
+
return entries;
|
|
473
|
+
}
|
|
474
|
+
catch (err) {
|
|
475
|
+
log.warn(`Failed to list LLM agent sessions: ${err instanceof Error ? err.message : String(err)}`);
|
|
476
|
+
return [];
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
async getSessionMessages(options, userId) {
|
|
480
|
+
if (!userId) {
|
|
481
|
+
throw new Error("getSessionMessages requires an authenticated userId");
|
|
482
|
+
}
|
|
483
|
+
try {
|
|
484
|
+
// Verify ownership before reading messages — Thread.find filters by
|
|
485
|
+
// userId, so a user can't read another user's transcript by guessing
|
|
486
|
+
// a thread id.
|
|
487
|
+
const thread = await DbThread.find(userId, options.sessionId);
|
|
488
|
+
if (!thread)
|
|
489
|
+
return [];
|
|
490
|
+
const [rows] = await DbMessage.paginate(options.sessionId, {
|
|
491
|
+
limit: 1000,
|
|
492
|
+
});
|
|
493
|
+
const out = [];
|
|
494
|
+
for (const row of rows) {
|
|
495
|
+
if (row.user_id !== userId)
|
|
496
|
+
continue;
|
|
497
|
+
if (row.agent_execution_id !== LLM_AGENT_MARKER)
|
|
498
|
+
continue;
|
|
499
|
+
if (row.role !== "user" && row.role !== "assistant")
|
|
500
|
+
continue;
|
|
501
|
+
const text = typeof row.content === "string"
|
|
502
|
+
? row.content
|
|
503
|
+
: Array.isArray(row.content)
|
|
504
|
+
? row.content
|
|
505
|
+
.filter((b) => b.type === "text" && typeof b.text === "string")
|
|
506
|
+
.map((b) => b.text)
|
|
507
|
+
.join("\n")
|
|
508
|
+
: "";
|
|
509
|
+
if (!text)
|
|
510
|
+
continue;
|
|
511
|
+
out.push({
|
|
512
|
+
type: row.role,
|
|
513
|
+
uuid: row.id,
|
|
514
|
+
session_id: options.sessionId,
|
|
515
|
+
text,
|
|
516
|
+
});
|
|
517
|
+
}
|
|
518
|
+
return out;
|
|
519
|
+
}
|
|
520
|
+
catch (err) {
|
|
521
|
+
log.warn(`Failed to get LLM agent session messages: ${err instanceof Error ? err.message : String(err)}`);
|
|
522
|
+
return [];
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
//# sourceMappingURL=llm-agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm-agent.js","sourceRoot":"","sources":["../../src/agent/llm-agent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP MCP server that exposes NodeTool UI tools.
|
|
3
|
+
*
|
|
4
|
+
* Implements the MCP Streamable HTTP transport so any agent SDK
|
|
5
|
+
* (Claude, Codex, OpenCode) can connect to it as an MCP server.
|
|
6
|
+
*
|
|
7
|
+
* Tool calls are forwarded to the renderer whose session originated the
|
|
8
|
+
* connection via the `AgentTransport` for execution against the live
|
|
9
|
+
* workflow graph. The session identity is encoded in the URL path as
|
|
10
|
+
* `/mcp/<sessionId>` so simultaneous sessions from different renderers
|
|
11
|
+
* can't clobber each other's tool routing.
|
|
12
|
+
*/
|
|
13
|
+
import type { AgentTransport } from "./transport.js";
|
|
14
|
+
/**
|
|
15
|
+
* Start (if needed) the MCP HTTP server and register `transport` as the
|
|
16
|
+
* executor for `sessionId`. Returns the session-scoped MCP URL to hand to
|
|
17
|
+
* the agent SDK.
|
|
18
|
+
*/
|
|
19
|
+
export declare function startMcpToolServer(transport: AgentTransport, sessionId: string): Promise<string>;
|
|
20
|
+
/** Update the transport associated with an existing session. */
|
|
21
|
+
export declare function setMcpToolServerTransport(transport: AgentTransport, sessionId: string): void;
|
|
22
|
+
/**
|
|
23
|
+
* Remove all session→transport mappings pointing at the given transport.
|
|
24
|
+
* Called when a renderer disconnects so we don't keep dead references.
|
|
25
|
+
*/
|
|
26
|
+
export declare function clearMcpToolServerTransport(transport: AgentTransport): void;
|
|
27
|
+
/** Drop a single session's transport mapping. */
|
|
28
|
+
export declare function clearMcpToolServerSession(sessionId: string): void;
|
|
29
|
+
/** Get the MCP server URL for an already-registered session, or null. */
|
|
30
|
+
export declare function getMcpToolServerUrl(sessionId: string): string | null;
|
|
31
|
+
/** Stop the MCP tool server. */
|
|
32
|
+
export declare function stopMcpToolServer(): void;
|
|
33
|
+
//# sourceMappingURL=mcp-tool-server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-tool-server.d.ts","sourceRoot":"","sources":["../../src/agent/mcp-tool-server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAWH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAqTrD;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,cAAc,EACzB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,CAAC,CAIjB;AAED,gEAAgE;AAChE,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,cAAc,EACzB,SAAS,EAAE,MAAM,GAChB,IAAI,CAEN;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,SAAS,EAAE,cAAc,GAAG,IAAI,CAM3E;AAED,iDAAiD;AACjD,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAEjE;AAED,yEAAyE;AACzE,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAKpE;AAED,gCAAgC;AAChC,wBAAgB,iBAAiB,IAAI,IAAI,CAQxC"}
|