u-foo 3.0.18 → 3.0.19
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/OPTIONAL_SKILLS/ufoo-bus-poll/SKILL.md +10 -6
- package/README.md +37 -17
- package/README.zh-CN.md +30 -19
- package/SKILLS/ufoo/SKILL.md +16 -8
- package/SKILLS/ufoo-bus/SKILL.md +16 -7
- package/bin/ufoo.js +19 -5
- package/package.json +2 -1
- package/src/app/chat/commandExecutor.js +11 -5
- package/src/app/cli/run.js +2 -3
- package/src/config.js +10 -0
- package/src/coordination/bus/subscriber.js +32 -0
- package/src/coordination/state/paths.js +4 -0
- package/src/runtime/contracts/eventContract.js +5 -0
- package/src/runtime/daemon/controlPlaneService.js +130 -12
- package/src/runtime/daemon/index.js +65 -0
- package/src/runtime/daemon/mcpConfigure.js +175 -0
- package/src/runtime/daemon/mcpControl.js +123 -0
- package/src/runtime/daemon/mcpHttpServer.js +412 -0
- package/src/runtime/daemon/mcpServer.js +94 -103
- package/src/runtime/daemon/mcpStdioProxy.js +247 -0
- package/src/runtime/daemon/projectRuntimeControlPlane.js +115 -0
- package/src/runtime/daemon/projectRuntimeGateway.js +358 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const {
|
|
4
|
+
IPC_REQUEST_TYPES,
|
|
5
|
+
IPC_RESPONSE_TYPES,
|
|
6
|
+
} = require("../contracts/eventContract");
|
|
7
|
+
const {
|
|
8
|
+
executeProjectRuntimeOperation,
|
|
9
|
+
} = require("./projectRuntimeGateway");
|
|
10
|
+
|
|
11
|
+
function writeResult(socket, payload) {
|
|
12
|
+
if (!socket || socket.destroyed) return;
|
|
13
|
+
socket.write(`${JSON.stringify({
|
|
14
|
+
type: IPC_RESPONSE_TYPES.CONTROL_PLANE_RESULT,
|
|
15
|
+
...payload,
|
|
16
|
+
})}\n`);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function createProjectRuntimeControlPlane(options = {}) {
|
|
20
|
+
const projectRoot = String(options.projectRoot || "").trim();
|
|
21
|
+
const execute = options.execute || executeProjectRuntimeOperation;
|
|
22
|
+
const activeCalls = new Map();
|
|
23
|
+
|
|
24
|
+
async function handleRequest(req, socket) {
|
|
25
|
+
if (!req || typeof req !== "object") return false;
|
|
26
|
+
if (req.type === IPC_REQUEST_TYPES.CONTROL_PLANE_CANCEL) {
|
|
27
|
+
const requestId = String(req.request_id || "");
|
|
28
|
+
const active = activeCalls.get(requestId);
|
|
29
|
+
if (active) active.abortController.abort();
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
if (req.type !== IPC_REQUEST_TYPES.CONTROL_PLANE_CALL) return false;
|
|
33
|
+
|
|
34
|
+
const requestId = String(req.request_id || "").trim();
|
|
35
|
+
const operation = String(req.operation || "").trim();
|
|
36
|
+
if (!requestId || !operation) {
|
|
37
|
+
writeResult(socket, {
|
|
38
|
+
request_id: requestId,
|
|
39
|
+
ok: false,
|
|
40
|
+
error: {
|
|
41
|
+
code: "invalid_control_plane_call",
|
|
42
|
+
message: "control_plane_call requires request_id and operation",
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
if (activeCalls.has(requestId)) {
|
|
48
|
+
writeResult(socket, {
|
|
49
|
+
request_id: requestId,
|
|
50
|
+
ok: false,
|
|
51
|
+
error: {
|
|
52
|
+
code: "duplicate_control_plane_call",
|
|
53
|
+
message: `control plane request is already active: ${requestId}`,
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const abortController = new AbortController();
|
|
60
|
+
const cancelOnClose = () => abortController.abort();
|
|
61
|
+
activeCalls.set(requestId, { abortController, socket });
|
|
62
|
+
socket.once("close", cancelOnClose);
|
|
63
|
+
try {
|
|
64
|
+
const result = await execute(
|
|
65
|
+
projectRoot,
|
|
66
|
+
operation,
|
|
67
|
+
req.arguments && typeof req.arguments === "object" ? req.arguments : {},
|
|
68
|
+
{
|
|
69
|
+
requestId,
|
|
70
|
+
toolCallId: req.tool_call_id,
|
|
71
|
+
signal: abortController.signal,
|
|
72
|
+
}
|
|
73
|
+
);
|
|
74
|
+
writeResult(socket, {
|
|
75
|
+
request_id: requestId,
|
|
76
|
+
ok: true,
|
|
77
|
+
result,
|
|
78
|
+
});
|
|
79
|
+
} catch (err) {
|
|
80
|
+
writeResult(socket, {
|
|
81
|
+
request_id: requestId,
|
|
82
|
+
ok: false,
|
|
83
|
+
error: {
|
|
84
|
+
code: err && err.code ? String(err.code) : "control_plane_error",
|
|
85
|
+
message: err && err.message ? err.message : String(err),
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
} finally {
|
|
89
|
+
socket.removeListener("close", cancelOnClose);
|
|
90
|
+
activeCalls.delete(requestId);
|
|
91
|
+
}
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function stop() {
|
|
96
|
+
for (const active of activeCalls.values()) {
|
|
97
|
+
active.abortController.abort();
|
|
98
|
+
}
|
|
99
|
+
activeCalls.clear();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function activeCount() {
|
|
103
|
+
return activeCalls.size;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return {
|
|
107
|
+
handleRequest,
|
|
108
|
+
stop,
|
|
109
|
+
activeCount,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
module.exports = {
|
|
114
|
+
createProjectRuntimeControlPlane,
|
|
115
|
+
};
|
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const crypto = require("crypto");
|
|
4
|
+
const net = require("net");
|
|
5
|
+
const { getUfooPaths } = require("../../coordination/state/paths");
|
|
6
|
+
const {
|
|
7
|
+
IPC_REQUEST_TYPES,
|
|
8
|
+
IPC_RESPONSE_TYPES,
|
|
9
|
+
} = require("../contracts/eventContract");
|
|
10
|
+
const {
|
|
11
|
+
assertToolAllowedForCallerTier,
|
|
12
|
+
} = require("../../tools/registry");
|
|
13
|
+
const { CALLER_TIERS } = require("../../tools/types");
|
|
14
|
+
|
|
15
|
+
const MCP_EXPOSED_SHARED_TOOLS = Object.freeze([
|
|
16
|
+
"read_project_registry",
|
|
17
|
+
"read_bus_summary",
|
|
18
|
+
"read_prompt_history",
|
|
19
|
+
"read_open_decisions",
|
|
20
|
+
"list_agents",
|
|
21
|
+
"dispatch_message",
|
|
22
|
+
"ack_bus",
|
|
23
|
+
]);
|
|
24
|
+
|
|
25
|
+
const CONTROL_PLANE_OPERATIONS = Object.freeze([
|
|
26
|
+
"register_agent",
|
|
27
|
+
"heartbeat_agent",
|
|
28
|
+
"publish_activity_state",
|
|
29
|
+
"update_agent_metadata",
|
|
30
|
+
"poll_inbox",
|
|
31
|
+
"wait_for_message",
|
|
32
|
+
"report_agent_status",
|
|
33
|
+
"unregister_agent",
|
|
34
|
+
]);
|
|
35
|
+
|
|
36
|
+
function stripRoutingArgs(args = {}) {
|
|
37
|
+
const next = { ...(args || {}) };
|
|
38
|
+
delete next.project_root;
|
|
39
|
+
delete next.projectRoot;
|
|
40
|
+
delete next.subscriber;
|
|
41
|
+
delete next.agent_handle;
|
|
42
|
+
delete next.agentHandle;
|
|
43
|
+
return next;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function unsupportedOperationError(operation = "") {
|
|
47
|
+
const err = new Error(`unsupported project runtime operation: ${operation}`);
|
|
48
|
+
err.code = "unsupported_project_runtime_operation";
|
|
49
|
+
return err;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function createControlPlaneHandlers(service = null) {
|
|
53
|
+
const resolvedService = service || require("./controlPlaneService");
|
|
54
|
+
return {
|
|
55
|
+
register_agent: (projectRoot, args) => resolvedService.registerAgent(projectRoot, args),
|
|
56
|
+
heartbeat_agent: (projectRoot, args) => resolvedService.heartbeatAgent(projectRoot, args),
|
|
57
|
+
publish_activity_state: (projectRoot, args) => resolvedService.publishActivityState(projectRoot, args),
|
|
58
|
+
update_agent_metadata: (projectRoot, args) => resolvedService.updateAgentMetadata(projectRoot, args),
|
|
59
|
+
poll_inbox: (projectRoot, args) => resolvedService.pollInbox(projectRoot, args),
|
|
60
|
+
wait_for_message: (projectRoot, args, context) => resolvedService.waitForMessage(projectRoot, args, {
|
|
61
|
+
signal: context.signal,
|
|
62
|
+
pollIntervalMs: context.waitPollIntervalMs,
|
|
63
|
+
heartbeatIntervalMs: context.waitHeartbeatIntervalMs,
|
|
64
|
+
now: context.waitNow,
|
|
65
|
+
sleep: context.waitSleep,
|
|
66
|
+
}),
|
|
67
|
+
report_agent_status: (projectRoot, args) => resolvedService.reportAgentStatus(projectRoot, args),
|
|
68
|
+
unregister_agent: (projectRoot, args) => resolvedService.unregisterAgent(projectRoot, args),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async function executeProjectRuntimeOperation(
|
|
73
|
+
projectRoot,
|
|
74
|
+
operation,
|
|
75
|
+
args = {},
|
|
76
|
+
context = {},
|
|
77
|
+
options = {}
|
|
78
|
+
) {
|
|
79
|
+
const name = String(operation || "").trim();
|
|
80
|
+
const handlers = options.controlPlaneHandlers
|
|
81
|
+
|| createControlPlaneHandlers(options.controlPlaneService);
|
|
82
|
+
const customHandler = handlers[name];
|
|
83
|
+
if (customHandler) {
|
|
84
|
+
return customHandler(projectRoot, args, context);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (!MCP_EXPOSED_SHARED_TOOLS.includes(name) || name === "read_project_registry") {
|
|
88
|
+
throw unsupportedOperationError(name);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (name === "dispatch_message" || name === "ack_bus") {
|
|
92
|
+
const subscriber = String(args.subscriber || args.source || context.subscriber || "").trim();
|
|
93
|
+
const bus = resolvedBusForAgentHandle(projectRoot, options);
|
|
94
|
+
assertExternalAgentHandle(bus, subscriber, args, options);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const tool = assertToolAllowedForCallerTier(name, CALLER_TIERS.WORKER, {
|
|
98
|
+
tool_call_id: context.toolCallId,
|
|
99
|
+
});
|
|
100
|
+
const subscriber = String(args.subscriber || args.source || context.subscriber || "").trim();
|
|
101
|
+
const toolArgs = stripRoutingArgs(args);
|
|
102
|
+
if (name === "dispatch_message" && !toolArgs.source && subscriber) {
|
|
103
|
+
toolArgs.source = subscriber;
|
|
104
|
+
}
|
|
105
|
+
return tool.handler({
|
|
106
|
+
projectRoot,
|
|
107
|
+
subscriber,
|
|
108
|
+
caller_tier: CALLER_TIERS.WORKER,
|
|
109
|
+
tool_call_id: context.toolCallId,
|
|
110
|
+
}, toolArgs);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function resolvedBusForAgentHandle(projectRoot, options = {}) {
|
|
114
|
+
const service = options.controlPlaneService || require("./controlPlaneService");
|
|
115
|
+
return service.ensureBusLoaded(projectRoot);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function assertExternalAgentHandle(bus, subscriber, args = {}, options = {}) {
|
|
119
|
+
const service = options.controlPlaneService || require("./controlPlaneService");
|
|
120
|
+
return service.assertAgentHandle(bus, subscriber, args);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
class LocalProjectRuntimeGateway {
|
|
124
|
+
constructor(options = {}) {
|
|
125
|
+
this.options = options;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
call(projectRoot, operation, args = {}, context = {}) {
|
|
129
|
+
return executeProjectRuntimeOperation(
|
|
130
|
+
projectRoot,
|
|
131
|
+
operation,
|
|
132
|
+
args,
|
|
133
|
+
context,
|
|
134
|
+
this.options
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
cancel() {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function projectRuntimeError(code, message) {
|
|
144
|
+
const err = new Error(String(message || "project runtime request failed"));
|
|
145
|
+
err.code = String(code || "project_runtime_error");
|
|
146
|
+
return err;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function connectProjectRuntimeSocket(sockPath, timeoutMs = 5000) {
|
|
150
|
+
return new Promise((resolve, reject) => {
|
|
151
|
+
let settled = false;
|
|
152
|
+
const socket = net.createConnection(sockPath);
|
|
153
|
+
const timer = setTimeout(() => {
|
|
154
|
+
if (settled) return;
|
|
155
|
+
settled = true;
|
|
156
|
+
socket.destroy();
|
|
157
|
+
reject(projectRuntimeError(
|
|
158
|
+
"project_runtime_connect_timeout",
|
|
159
|
+
`project runtime connect timeout: ${sockPath}`
|
|
160
|
+
));
|
|
161
|
+
}, timeoutMs);
|
|
162
|
+
if (typeof timer.unref === "function") timer.unref();
|
|
163
|
+
|
|
164
|
+
socket.once("connect", () => {
|
|
165
|
+
if (settled) return;
|
|
166
|
+
settled = true;
|
|
167
|
+
clearTimeout(timer);
|
|
168
|
+
resolve(socket);
|
|
169
|
+
});
|
|
170
|
+
socket.once("error", (err) => {
|
|
171
|
+
if (settled) return;
|
|
172
|
+
settled = true;
|
|
173
|
+
clearTimeout(timer);
|
|
174
|
+
reject(projectRuntimeError(
|
|
175
|
+
err && err.code ? String(err.code) : "project_runtime_unavailable",
|
|
176
|
+
`failed to connect project runtime: ${err && err.message ? err.message : err}`
|
|
177
|
+
));
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function resolveCallTimeoutMs(operation, args = {}, fallbackMs = 15000) {
|
|
183
|
+
if (operation !== "wait_for_message") return fallbackMs;
|
|
184
|
+
const timeoutSeconds = Number(args.timeout_seconds ?? args.timeoutSeconds ?? 600);
|
|
185
|
+
const waitMs = Number.isFinite(timeoutSeconds) && timeoutSeconds > 0
|
|
186
|
+
? timeoutSeconds * 1000
|
|
187
|
+
: 600000;
|
|
188
|
+
return waitMs + 5000;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
class SocketProjectRuntimeGateway {
|
|
192
|
+
constructor(options = {}) {
|
|
193
|
+
this.connect = options.connect || connectProjectRuntimeSocket;
|
|
194
|
+
this.socketPath = options.socketPath
|
|
195
|
+
|| ((projectRoot) => getUfooPaths(projectRoot).ufooSock);
|
|
196
|
+
this.connectTimeoutMs = Number(options.connectTimeoutMs) || 5000;
|
|
197
|
+
this.callTimeoutMs = Number(options.callTimeoutMs) || 15000;
|
|
198
|
+
this.activeCalls = new Map();
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
async call(projectRoot, operation, args = {}, context = {}) {
|
|
202
|
+
if (context.signal && context.signal.aborted) {
|
|
203
|
+
throw projectRuntimeError("request_cancelled", "project runtime request was cancelled");
|
|
204
|
+
}
|
|
205
|
+
const sockPath = this.socketPath(projectRoot);
|
|
206
|
+
const socket = await this.connect(sockPath, this.connectTimeoutMs);
|
|
207
|
+
const requestId = String(
|
|
208
|
+
context.requestId
|
|
209
|
+
|| crypto.randomUUID()
|
|
210
|
+
);
|
|
211
|
+
const timeoutMs = resolveCallTimeoutMs(operation, args, this.callTimeoutMs);
|
|
212
|
+
|
|
213
|
+
return new Promise((resolve, reject) => {
|
|
214
|
+
let buffer = "";
|
|
215
|
+
let settled = false;
|
|
216
|
+
let timer = null;
|
|
217
|
+
|
|
218
|
+
const cleanup = () => {
|
|
219
|
+
if (timer) clearTimeout(timer);
|
|
220
|
+
timer = null;
|
|
221
|
+
this.activeCalls.delete(requestId);
|
|
222
|
+
if (context.signal) context.signal.removeEventListener("abort", onAbort);
|
|
223
|
+
socket.removeAllListeners();
|
|
224
|
+
try {
|
|
225
|
+
socket.end();
|
|
226
|
+
} catch {
|
|
227
|
+
// ignore close errors
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
const finishResolve = (value) => {
|
|
232
|
+
if (settled) return;
|
|
233
|
+
settled = true;
|
|
234
|
+
cleanup();
|
|
235
|
+
resolve(value);
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
const finishReject = (err) => {
|
|
239
|
+
if (settled) return;
|
|
240
|
+
settled = true;
|
|
241
|
+
cleanup();
|
|
242
|
+
reject(err);
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
const onAbort = () => {
|
|
246
|
+
if (settled) return;
|
|
247
|
+
try {
|
|
248
|
+
socket.write(`${JSON.stringify({
|
|
249
|
+
type: IPC_REQUEST_TYPES.CONTROL_PLANE_CANCEL,
|
|
250
|
+
request_id: requestId,
|
|
251
|
+
})}\n`);
|
|
252
|
+
} catch {
|
|
253
|
+
// best-effort cancellation
|
|
254
|
+
}
|
|
255
|
+
try {
|
|
256
|
+
socket.destroy();
|
|
257
|
+
} catch {
|
|
258
|
+
// ignore close errors
|
|
259
|
+
}
|
|
260
|
+
finishReject(projectRuntimeError(
|
|
261
|
+
"request_cancelled",
|
|
262
|
+
"project runtime request was cancelled"
|
|
263
|
+
));
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
this.activeCalls.set(requestId, { cancel: onAbort, socket });
|
|
267
|
+
if (context.signal) {
|
|
268
|
+
context.signal.addEventListener("abort", onAbort, { once: true });
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
socket.on("data", (chunk) => {
|
|
272
|
+
buffer += chunk.toString("utf8");
|
|
273
|
+
const lines = buffer.split(/\r?\n/);
|
|
274
|
+
buffer = lines.pop() || "";
|
|
275
|
+
for (const line of lines) {
|
|
276
|
+
if (!line.trim()) continue;
|
|
277
|
+
let payload;
|
|
278
|
+
try {
|
|
279
|
+
payload = JSON.parse(line);
|
|
280
|
+
} catch {
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
if (
|
|
284
|
+
payload.type !== IPC_RESPONSE_TYPES.CONTROL_PLANE_RESULT
|
|
285
|
+
|| String(payload.request_id || "") !== requestId
|
|
286
|
+
) {
|
|
287
|
+
continue;
|
|
288
|
+
}
|
|
289
|
+
if (payload.ok === false) {
|
|
290
|
+
const error = payload.error && typeof payload.error === "object"
|
|
291
|
+
? payload.error
|
|
292
|
+
: {};
|
|
293
|
+
finishReject(projectRuntimeError(
|
|
294
|
+
error.code || "project_runtime_error",
|
|
295
|
+
error.message || "project runtime request failed"
|
|
296
|
+
));
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
finishResolve(payload.result);
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
socket.once("error", (err) => {
|
|
304
|
+
finishReject(projectRuntimeError(
|
|
305
|
+
err && err.code ? String(err.code) : "project_runtime_connection_error",
|
|
306
|
+
err && err.message ? err.message : String(err)
|
|
307
|
+
));
|
|
308
|
+
});
|
|
309
|
+
socket.once("close", () => {
|
|
310
|
+
finishReject(projectRuntimeError(
|
|
311
|
+
"project_runtime_connection_closed",
|
|
312
|
+
"project runtime connection closed before a result was returned"
|
|
313
|
+
));
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
timer = setTimeout(() => {
|
|
317
|
+
onAbort();
|
|
318
|
+
}, timeoutMs);
|
|
319
|
+
if (typeof timer.unref === "function") timer.unref();
|
|
320
|
+
|
|
321
|
+
socket.write(`${JSON.stringify({
|
|
322
|
+
type: IPC_REQUEST_TYPES.CONTROL_PLANE_CALL,
|
|
323
|
+
request_id: requestId,
|
|
324
|
+
operation,
|
|
325
|
+
arguments: args,
|
|
326
|
+
tool_call_id: context.toolCallId,
|
|
327
|
+
})}\n`);
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
cancel(requestId) {
|
|
332
|
+
const active = this.activeCalls.get(String(requestId || ""));
|
|
333
|
+
if (!active) return false;
|
|
334
|
+
active.cancel();
|
|
335
|
+
return true;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
function createLocalProjectRuntimeGateway(options = {}) {
|
|
340
|
+
return new LocalProjectRuntimeGateway(options);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
function createSocketProjectRuntimeGateway(options = {}) {
|
|
344
|
+
return new SocketProjectRuntimeGateway(options);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
module.exports = {
|
|
348
|
+
MCP_EXPOSED_SHARED_TOOLS,
|
|
349
|
+
CONTROL_PLANE_OPERATIONS,
|
|
350
|
+
stripRoutingArgs,
|
|
351
|
+
executeProjectRuntimeOperation,
|
|
352
|
+
LocalProjectRuntimeGateway,
|
|
353
|
+
SocketProjectRuntimeGateway,
|
|
354
|
+
createLocalProjectRuntimeGateway,
|
|
355
|
+
createSocketProjectRuntimeGateway,
|
|
356
|
+
connectProjectRuntimeSocket,
|
|
357
|
+
resolveCallTimeoutMs,
|
|
358
|
+
};
|