@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.
Files changed (261) hide show
  1. package/dist/agent/agent-runtime.d.ts +47 -0
  2. package/dist/agent/agent-runtime.d.ts.map +1 -0
  3. package/dist/agent/agent-runtime.js +577 -0
  4. package/dist/agent/agent-runtime.js.map +1 -0
  5. package/dist/agent/codex-agent.d.ts +41 -0
  6. package/dist/agent/codex-agent.d.ts.map +1 -0
  7. package/dist/agent/codex-agent.js +334 -0
  8. package/dist/agent/codex-agent.js.map +1 -0
  9. package/dist/agent/index.d.ts +6 -0
  10. package/dist/agent/index.d.ts.map +1 -0
  11. package/dist/agent/index.js +4 -0
  12. package/dist/agent/index.js.map +1 -0
  13. package/dist/agent/llm-agent.d.ts +51 -0
  14. package/dist/agent/llm-agent.d.ts.map +1 -0
  15. package/dist/agent/llm-agent.js +526 -0
  16. package/dist/agent/llm-agent.js.map +1 -0
  17. package/dist/agent/mcp-tool-server.d.ts +33 -0
  18. package/dist/agent/mcp-tool-server.d.ts.map +1 -0
  19. package/dist/agent/mcp-tool-server.js +292 -0
  20. package/dist/agent/mcp-tool-server.js.map +1 -0
  21. package/dist/agent/opencode-agent.d.ts +32 -0
  22. package/dist/agent/opencode-agent.d.ts.map +1 -0
  23. package/dist/agent/opencode-agent.js +332 -0
  24. package/dist/agent/opencode-agent.js.map +1 -0
  25. package/dist/agent/pi-agent.d.ts +42 -0
  26. package/dist/agent/pi-agent.d.ts.map +1 -0
  27. package/dist/agent/pi-agent.js +429 -0
  28. package/dist/agent/pi-agent.js.map +1 -0
  29. package/dist/agent/sdk-provider.d.ts +46 -0
  30. package/dist/agent/sdk-provider.d.ts.map +1 -0
  31. package/dist/agent/sdk-provider.js +50 -0
  32. package/dist/agent/sdk-provider.js.map +1 -0
  33. package/dist/agent/socket-route.d.ts +11 -0
  34. package/dist/agent/socket-route.d.ts.map +1 -0
  35. package/dist/agent/socket-route.js +262 -0
  36. package/dist/agent/socket-route.js.map +1 -0
  37. package/dist/agent/transport.d.ts +39 -0
  38. package/dist/agent/transport.d.ts.map +1 -0
  39. package/dist/agent/transport.js +17 -0
  40. package/dist/agent/transport.js.map +1 -0
  41. package/dist/agent/types.d.ts +11 -0
  42. package/dist/agent/types.d.ts.map +1 -0
  43. package/dist/agent/types.js +10 -0
  44. package/dist/agent/types.js.map +1 -0
  45. package/dist/collection-api.d.ts +14 -0
  46. package/dist/collection-api.d.ts.map +1 -0
  47. package/dist/collection-api.js +75 -0
  48. package/dist/collection-api.js.map +1 -0
  49. package/dist/error-codes.d.ts +3 -0
  50. package/dist/error-codes.d.ts.map +1 -0
  51. package/dist/error-codes.js +2 -0
  52. package/dist/error-codes.js.map +1 -0
  53. package/dist/file-api.d.ts +12 -0
  54. package/dist/file-api.d.ts.map +1 -0
  55. package/dist/file-api.js +76 -0
  56. package/dist/file-api.js.map +1 -0
  57. package/dist/http-api.d.ts +94 -0
  58. package/dist/http-api.d.ts.map +1 -0
  59. package/dist/http-api.js +1472 -0
  60. package/dist/http-api.js.map +1 -0
  61. package/dist/index.d.ts +6 -0
  62. package/dist/index.d.ts.map +1 -0
  63. package/dist/index.js +6 -0
  64. package/dist/index.js.map +1 -0
  65. package/dist/lib/asset-paths.d.ts +10 -0
  66. package/dist/lib/asset-paths.d.ts.map +1 -0
  67. package/dist/lib/asset-paths.js +45 -0
  68. package/dist/lib/asset-paths.js.map +1 -0
  69. package/dist/lib/bridge.d.ts +8 -0
  70. package/dist/lib/bridge.d.ts.map +1 -0
  71. package/dist/lib/bridge.js +70 -0
  72. package/dist/lib/bridge.js.map +1 -0
  73. package/dist/mcp-server.d.ts +32 -0
  74. package/dist/mcp-server.d.ts.map +1 -0
  75. package/dist/mcp-server.js +842 -0
  76. package/dist/mcp-server.js.map +1 -0
  77. package/dist/models-api.d.ts +12 -0
  78. package/dist/models-api.d.ts.map +1 -0
  79. package/dist/models-api.js +730 -0
  80. package/dist/models-api.js.map +1 -0
  81. package/dist/oauth-api.d.ts +28 -0
  82. package/dist/oauth-api.d.ts.map +1 -0
  83. package/dist/oauth-api.js +681 -0
  84. package/dist/oauth-api.js.map +1 -0
  85. package/dist/openai-api.d.ts +63 -0
  86. package/dist/openai-api.d.ts.map +1 -0
  87. package/dist/openai-api.js +359 -0
  88. package/dist/openai-api.js.map +1 -0
  89. package/dist/plugins/websocket.d.ts +14 -0
  90. package/dist/plugins/websocket.d.ts.map +1 -0
  91. package/dist/plugins/websocket.js +431 -0
  92. package/dist/plugins/websocket.js.map +1 -0
  93. package/dist/resolve-media-urls.d.ts +19 -0
  94. package/dist/resolve-media-urls.d.ts.map +1 -0
  95. package/dist/resolve-media-urls.js +109 -0
  96. package/dist/resolve-media-urls.js.map +1 -0
  97. package/dist/routes/assets.d.ts +22 -0
  98. package/dist/routes/assets.d.ts.map +1 -0
  99. package/dist/routes/assets.js +168 -0
  100. package/dist/routes/assets.js.map +1 -0
  101. package/dist/routes/collections.d.ts +16 -0
  102. package/dist/routes/collections.d.ts.map +1 -0
  103. package/dist/routes/collections.js +32 -0
  104. package/dist/routes/collections.js.map +1 -0
  105. package/dist/routes/files.d.ts +12 -0
  106. package/dist/routes/files.d.ts.map +1 -0
  107. package/dist/routes/files.js +11 -0
  108. package/dist/routes/files.js.map +1 -0
  109. package/dist/routes/health.d.ts +4 -0
  110. package/dist/routes/health.d.ts.map +1 -0
  111. package/dist/routes/health.js +41 -0
  112. package/dist/routes/health.js.map +1 -0
  113. package/dist/routes/jobs.d.ts +16 -0
  114. package/dist/routes/jobs.d.ts.map +1 -0
  115. package/dist/routes/jobs.js +25 -0
  116. package/dist/routes/jobs.js.map +1 -0
  117. package/dist/routes/nodes.d.ts +8 -0
  118. package/dist/routes/nodes.d.ts.map +1 -0
  119. package/dist/routes/nodes.js +124 -0
  120. package/dist/routes/nodes.js.map +1 -0
  121. package/dist/routes/oauth.d.ts +8 -0
  122. package/dist/routes/oauth.d.ts.map +1 -0
  123. package/dist/routes/oauth.js +19 -0
  124. package/dist/routes/oauth.js.map +1 -0
  125. package/dist/routes/openai.d.ts +8 -0
  126. package/dist/routes/openai.d.ts.map +1 -0
  127. package/dist/routes/openai.js +20 -0
  128. package/dist/routes/openai.js.map +1 -0
  129. package/dist/routes/storage.d.ts +12 -0
  130. package/dist/routes/storage.d.ts.map +1 -0
  131. package/dist/routes/storage.js +13 -0
  132. package/dist/routes/storage.js.map +1 -0
  133. package/dist/routes/workflows.d.ts +18 -0
  134. package/dist/routes/workflows.d.ts.map +1 -0
  135. package/dist/routes/workflows.js +25 -0
  136. package/dist/routes/workflows.js.map +1 -0
  137. package/dist/routes/workspace.d.ts +15 -0
  138. package/dist/routes/workspace.d.ts.map +1 -0
  139. package/dist/routes/workspace.js +24 -0
  140. package/dist/routes/workspace.js.map +1 -0
  141. package/dist/screenshot-server.d.ts +21 -0
  142. package/dist/screenshot-server.d.ts.map +1 -0
  143. package/dist/screenshot-server.js +222 -0
  144. package/dist/screenshot-server.js.map +1 -0
  145. package/dist/server.d.ts +10 -0
  146. package/dist/server.d.ts.map +1 -0
  147. package/dist/server.js +783 -0
  148. package/dist/server.js.map +1 -0
  149. package/dist/settings-registry.d.ts +29 -0
  150. package/dist/settings-registry.d.ts.map +1 -0
  151. package/dist/settings-registry.js +117 -0
  152. package/dist/settings-registry.js.map +1 -0
  153. package/dist/storage-api.d.ts +5 -0
  154. package/dist/storage-api.d.ts.map +1 -0
  155. package/dist/storage-api.js +221 -0
  156. package/dist/storage-api.js.map +1 -0
  157. package/dist/test-ui-server.d.ts +19 -0
  158. package/dist/test-ui-server.d.ts.map +1 -0
  159. package/dist/test-ui-server.js +1256 -0
  160. package/dist/test-ui-server.js.map +1 -0
  161. package/dist/trpc/context.d.ts +21 -0
  162. package/dist/trpc/context.d.ts.map +1 -0
  163. package/dist/trpc/context.js +10 -0
  164. package/dist/trpc/context.js.map +1 -0
  165. package/dist/trpc/error-formatter.d.ts +18 -0
  166. package/dist/trpc/error-formatter.d.ts.map +1 -0
  167. package/dist/trpc/error-formatter.js +41 -0
  168. package/dist/trpc/error-formatter.js.map +1 -0
  169. package/dist/trpc/index.d.ts +18 -0
  170. package/dist/trpc/index.d.ts.map +1 -0
  171. package/dist/trpc/index.js +13 -0
  172. package/dist/trpc/index.js.map +1 -0
  173. package/dist/trpc/middleware.d.ts +8 -0
  174. package/dist/trpc/middleware.d.ts.map +1 -0
  175. package/dist/trpc/middleware.js +12 -0
  176. package/dist/trpc/middleware.js.map +1 -0
  177. package/dist/trpc/router.d.ts +2543 -0
  178. package/dist/trpc/router.d.ts.map +1 -0
  179. package/dist/trpc/router.js +43 -0
  180. package/dist/trpc/router.js.map +1 -0
  181. package/dist/trpc/routers/assets.d.ts +229 -0
  182. package/dist/trpc/routers/assets.d.ts.map +1 -0
  183. package/dist/trpc/routers/assets.js +263 -0
  184. package/dist/trpc/routers/assets.js.map +1 -0
  185. package/dist/trpc/routers/collections.d.ts +88 -0
  186. package/dist/trpc/routers/collections.d.ts.map +1 -0
  187. package/dist/trpc/routers/collections.js +166 -0
  188. package/dist/trpc/routers/collections.js.map +1 -0
  189. package/dist/trpc/routers/costs.d.ts +129 -0
  190. package/dist/trpc/routers/costs.d.ts.map +1 -0
  191. package/dist/trpc/routers/costs.js +95 -0
  192. package/dist/trpc/routers/costs.js.map +1 -0
  193. package/dist/trpc/routers/files.d.ts +34 -0
  194. package/dist/trpc/routers/files.d.ts.map +1 -0
  195. package/dist/trpc/routers/files.js +92 -0
  196. package/dist/trpc/routers/files.js.map +1 -0
  197. package/dist/trpc/routers/jobs.d.ts +92 -0
  198. package/dist/trpc/routers/jobs.d.ts.map +1 -0
  199. package/dist/trpc/routers/jobs.js +100 -0
  200. package/dist/trpc/routers/jobs.js.map +1 -0
  201. package/dist/trpc/routers/mcp-config.d.ts +69 -0
  202. package/dist/trpc/routers/mcp-config.d.ts.map +1 -0
  203. package/dist/trpc/routers/mcp-config.js +290 -0
  204. package/dist/trpc/routers/mcp-config.js.map +1 -0
  205. package/dist/trpc/routers/messages.d.ts +121 -0
  206. package/dist/trpc/routers/messages.d.ts.map +1 -0
  207. package/dist/trpc/routers/messages.js +113 -0
  208. package/dist/trpc/routers/messages.js.map +1 -0
  209. package/dist/trpc/routers/models.d.ts +748 -0
  210. package/dist/trpc/routers/models.d.ts.map +1 -0
  211. package/dist/trpc/routers/models.js +1107 -0
  212. package/dist/trpc/routers/models.js.map +1 -0
  213. package/dist/trpc/routers/nodes.d.ts +48 -0
  214. package/dist/trpc/routers/nodes.d.ts.map +1 -0
  215. package/dist/trpc/routers/nodes.js +57 -0
  216. package/dist/trpc/routers/nodes.js.map +1 -0
  217. package/dist/trpc/routers/sandboxes.d.ts +64 -0
  218. package/dist/trpc/routers/sandboxes.d.ts.map +1 -0
  219. package/dist/trpc/routers/sandboxes.js +327 -0
  220. package/dist/trpc/routers/sandboxes.js.map +1 -0
  221. package/dist/trpc/routers/settings.d.ts +113 -0
  222. package/dist/trpc/routers/settings.d.ts.map +1 -0
  223. package/dist/trpc/routers/settings.js +193 -0
  224. package/dist/trpc/routers/settings.js.map +1 -0
  225. package/dist/trpc/routers/skills.d.ts +41 -0
  226. package/dist/trpc/routers/skills.d.ts.map +1 -0
  227. package/dist/trpc/routers/skills.js +194 -0
  228. package/dist/trpc/routers/skills.js.map +1 -0
  229. package/dist/trpc/routers/storage.d.ts +44 -0
  230. package/dist/trpc/routers/storage.d.ts.map +1 -0
  231. package/dist/trpc/routers/storage.js +153 -0
  232. package/dist/trpc/routers/storage.js.map +1 -0
  233. package/dist/trpc/routers/threads.d.ts +95 -0
  234. package/dist/trpc/routers/threads.d.ts.map +1 -0
  235. package/dist/trpc/routers/threads.js +150 -0
  236. package/dist/trpc/routers/threads.js.map +1 -0
  237. package/dist/trpc/routers/users.d.ts +79 -0
  238. package/dist/trpc/routers/users.d.ts.map +1 -0
  239. package/dist/trpc/routers/users.js +125 -0
  240. package/dist/trpc/routers/users.js.map +1 -0
  241. package/dist/trpc/routers/workflows.d.ts +681 -0
  242. package/dist/trpc/routers/workflows.d.ts.map +1 -0
  243. package/dist/trpc/routers/workflows.js +725 -0
  244. package/dist/trpc/routers/workflows.js.map +1 -0
  245. package/dist/trpc/routers/workspace.d.ts +127 -0
  246. package/dist/trpc/routers/workspace.d.ts.map +1 -0
  247. package/dist/trpc/routers/workspace.js +203 -0
  248. package/dist/trpc/routers/workspace.js.map +1 -0
  249. package/dist/unified-websocket-runner.d.ts +280 -0
  250. package/dist/unified-websocket-runner.d.ts.map +1 -0
  251. package/dist/unified-websocket-runner.js +3840 -0
  252. package/dist/unified-websocket-runner.js.map +1 -0
  253. package/dist/workspace-api.d.ts +14 -0
  254. package/dist/workspace-api.d.ts.map +1 -0
  255. package/dist/workspace-api.js +104 -0
  256. package/dist/workspace-api.js.map +1 -0
  257. package/dist/ws-adapter.d.ts +25 -0
  258. package/dist/ws-adapter.d.ts.map +1 -0
  259. package/dist/ws-adapter.js +63 -0
  260. package/dist/ws-adapter.js.map +1 -0
  261. 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"}