@warlock.js/ai-tools 4.5.0
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/CHANGELOG.md +22 -0
- package/LICENSE +21 -0
- package/README.md +164 -0
- package/cjs/index.cjs +2519 -0
- package/cjs/index.cjs.map +1 -0
- package/esm/contracts/http.type.d.mts +96 -0
- package/esm/contracts/http.type.d.mts.map +1 -0
- package/esm/contracts/index.d.mts +4 -0
- package/esm/contracts/mcp.type.d.mts +216 -0
- package/esm/contracts/mcp.type.d.mts.map +1 -0
- package/esm/contracts/utility.type.d.mts +96 -0
- package/esm/contracts/utility.type.d.mts.map +1 -0
- package/esm/contracts/web.type.d.mts +136 -0
- package/esm/contracts/web.type.d.mts.map +1 -0
- package/esm/errors.d.mts +225 -0
- package/esm/errors.d.mts.map +1 -0
- package/esm/errors.mjs +136 -0
- package/esm/errors.mjs.map +1 -0
- package/esm/http/http-request.d.mts +57 -0
- package/esm/http/http-request.d.mts.map +1 -0
- package/esm/http/http-request.mjs +221 -0
- package/esm/http/http-request.mjs.map +1 -0
- package/esm/index.d.mts +19 -0
- package/esm/index.mjs +15 -0
- package/esm/mcp/client.mjs +199 -0
- package/esm/mcp/client.mjs.map +1 -0
- package/esm/mcp/index.d.mts +43 -0
- package/esm/mcp/index.d.mts.map +1 -0
- package/esm/mcp/index.mjs +19 -0
- package/esm/mcp/index.mjs.map +1 -0
- package/esm/mcp/json-schema-to-standard.d.mts +34 -0
- package/esm/mcp/json-schema-to-standard.d.mts.map +1 -0
- package/esm/mcp/json-schema-to-standard.mjs +147 -0
- package/esm/mcp/json-schema-to-standard.mjs.map +1 -0
- package/esm/mcp/serve.d.mts +46 -0
- package/esm/mcp/serve.d.mts.map +1 -0
- package/esm/mcp/serve.mjs +264 -0
- package/esm/mcp/serve.mjs.map +1 -0
- package/esm/mcp/transport.d.mts +48 -0
- package/esm/mcp/transport.d.mts.map +1 -0
- package/esm/mcp/transport.mjs +381 -0
- package/esm/mcp/transport.mjs.map +1 -0
- package/esm/mcp/transport.type.d.mts +51 -0
- package/esm/mcp/transport.type.d.mts.map +1 -0
- package/esm/node_modules/@standard-schema/spec/dist/index.d.mts +80 -0
- package/esm/node_modules/@standard-schema/spec/dist/index.d.mts.map +1 -0
- package/esm/register.d.mts +55 -0
- package/esm/register.d.mts.map +1 -0
- package/esm/register.mjs +21 -0
- package/esm/register.mjs.map +1 -0
- package/esm/schema.mjs +127 -0
- package/esm/schema.mjs.map +1 -0
- package/esm/utility/calculator.d.mts +35 -0
- package/esm/utility/calculator.d.mts.map +1 -0
- package/esm/utility/calculator.mjs +272 -0
- package/esm/utility/calculator.mjs.map +1 -0
- package/esm/utility/date-time.d.mts +57 -0
- package/esm/utility/date-time.d.mts.map +1 -0
- package/esm/utility/date-time.mjs +193 -0
- package/esm/utility/date-time.mjs.map +1 -0
- package/esm/utility/index.d.mts +2 -0
- package/esm/utility/index.mjs +4 -0
- package/esm/utility/schema.mjs +114 -0
- package/esm/utility/schema.mjs.map +1 -0
- package/esm/web/fetch-url.d.mts +39 -0
- package/esm/web/fetch-url.d.mts.map +1 -0
- package/esm/web/fetch-url.mjs +228 -0
- package/esm/web/fetch-url.mjs.map +1 -0
- package/esm/web/index.d.mts +2 -0
- package/esm/web/index.mjs +4 -0
- package/esm/web/schema.mjs +86 -0
- package/esm/web/schema.mjs.map +1 -0
- package/esm/web/web-search.d.mts +38 -0
- package/esm/web/web-search.d.mts.map +1 -0
- package/esm/web/web-search.mjs +167 -0
- package/esm/web/web-search.mjs.map +1 -0
- package/llms-full.txt +326 -0
- package/llms.txt +11 -0
- package/package.json +45 -0
- package/skills/README.md +17 -0
- package/skills/connect-mcp-server/SKILL.md +98 -0
- package/skills/expose-as-mcp-server/SKILL.md +85 -0
- package/skills/use-web-and-http-tools/SKILL.md +125 -0
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
import { McpTransportError } from "../errors.mjs";
|
|
2
|
+
import { spawn } from "node:child_process";
|
|
3
|
+
import { createInterface } from "node:readline";
|
|
4
|
+
|
|
5
|
+
//#region ../@warlock.js/ai-tools/src/mcp/transport.ts
|
|
6
|
+
/** Default per-request wait before a transport call is abandoned. */
|
|
7
|
+
const DEFAULT_REQUEST_TIMEOUT_MS = 3e4;
|
|
8
|
+
/** The JSON-RPC version literal every outbound message carries. */
|
|
9
|
+
const JSONRPC_VERSION = "2.0";
|
|
10
|
+
/**
|
|
11
|
+
* Wire a per-call timeout and an optional caller `AbortSignal` onto a
|
|
12
|
+
* pending request, returning a `cleanup()` that tears both down. The
|
|
13
|
+
* `onSettle` callback removes the pending entry from whatever registry the
|
|
14
|
+
* transport keeps so a late response can't double-settle.
|
|
15
|
+
*/
|
|
16
|
+
function armCall(reject, method, options, onSettle) {
|
|
17
|
+
const timeoutMs = options?.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
|
|
18
|
+
const timer = setTimeout(() => {
|
|
19
|
+
onSettle();
|
|
20
|
+
reject(new McpTransportError(`MCP request "${method}" timed out after ${timeoutMs}ms.`, {
|
|
21
|
+
type: "timeout",
|
|
22
|
+
method
|
|
23
|
+
}));
|
|
24
|
+
}, timeoutMs);
|
|
25
|
+
const onAbort = () => {
|
|
26
|
+
cleanup();
|
|
27
|
+
reject(new McpTransportError(`MCP request "${method}" was aborted.`, {
|
|
28
|
+
type: "closed",
|
|
29
|
+
method
|
|
30
|
+
}));
|
|
31
|
+
};
|
|
32
|
+
const signal = options?.signal;
|
|
33
|
+
if (signal) if (signal.aborted) queueMicrotask(onAbort);
|
|
34
|
+
else signal.addEventListener("abort", onAbort, { once: true });
|
|
35
|
+
function cleanup() {
|
|
36
|
+
clearTimeout(timer);
|
|
37
|
+
if (signal) signal.removeEventListener("abort", onAbort);
|
|
38
|
+
}
|
|
39
|
+
return cleanup;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* The stdio transport — spawns a child process and speaks JSON-RPC over
|
|
43
|
+
* its stdin/stdout, one JSON object per line (newline-delimited framing).
|
|
44
|
+
* Uses only Node built-ins (`node:child_process` + `node:readline`); no
|
|
45
|
+
* dependency.
|
|
46
|
+
*
|
|
47
|
+
* Constructed via {@link createStdioTransport}; the class itself is
|
|
48
|
+
* internal.
|
|
49
|
+
*/
|
|
50
|
+
var StdioTransport = class {
|
|
51
|
+
constructor(transport) {
|
|
52
|
+
this.pending = /* @__PURE__ */ new Map();
|
|
53
|
+
this.nextId = 1;
|
|
54
|
+
this.closed = false;
|
|
55
|
+
let child;
|
|
56
|
+
try {
|
|
57
|
+
child = spawn(transport.command, transport.args ?? [], {
|
|
58
|
+
env: transport.env,
|
|
59
|
+
stdio: [
|
|
60
|
+
"pipe",
|
|
61
|
+
"pipe",
|
|
62
|
+
"pipe"
|
|
63
|
+
]
|
|
64
|
+
});
|
|
65
|
+
} catch (cause) {
|
|
66
|
+
const message = cause instanceof Error ? cause.message : String(cause);
|
|
67
|
+
throw new McpTransportError(`MCP stdio transport could not spawn "${transport.command}": ${message}`, {
|
|
68
|
+
type: "connect",
|
|
69
|
+
cause
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
this.child = child;
|
|
73
|
+
this.reader = createInterface({ input: child.stdout });
|
|
74
|
+
this.reader.on("line", (line) => this.onLine(line));
|
|
75
|
+
child.on("exit", (code) => this.failAll("connect", `child exited with code ${code ?? "null"}`));
|
|
76
|
+
child.on("error", (error) => this.failAll("connect", error.message));
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Parse one stdout line and route it to its pending request. Non-JSON
|
|
80
|
+
* lines (a server logging to stdout) and messages with no matching `id`
|
|
81
|
+
* (notifications, stray responses) are ignored — robustness over strictness.
|
|
82
|
+
*/
|
|
83
|
+
onLine(line) {
|
|
84
|
+
const trimmed = line.trim();
|
|
85
|
+
if (!trimmed) return;
|
|
86
|
+
let message;
|
|
87
|
+
try {
|
|
88
|
+
message = JSON.parse(trimmed);
|
|
89
|
+
} catch {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
if (message.id === void 0 || message.id === null) return;
|
|
93
|
+
const call = this.pending.get(message.id);
|
|
94
|
+
if (!call) return;
|
|
95
|
+
this.pending.delete(message.id);
|
|
96
|
+
call.cleanup();
|
|
97
|
+
call.resolve(message);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Reject every pending call (and mark the transport unusable) when the
|
|
101
|
+
* child dies or errors — so a hung server can never leave a caller
|
|
102
|
+
* waiting forever.
|
|
103
|
+
*/
|
|
104
|
+
failAll(type, reason) {
|
|
105
|
+
this.closed = true;
|
|
106
|
+
for (const [id, call] of this.pending) {
|
|
107
|
+
this.pending.delete(id);
|
|
108
|
+
call.cleanup();
|
|
109
|
+
call.reject(new McpTransportError(`MCP stdio transport failed: ${reason}.`, { type }));
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
request(request, options) {
|
|
113
|
+
if (this.closed) return Promise.reject(new McpTransportError("MCP stdio transport is closed.", {
|
|
114
|
+
type: "closed",
|
|
115
|
+
method: request.method
|
|
116
|
+
}));
|
|
117
|
+
const id = request.id;
|
|
118
|
+
return new Promise((resolve, reject) => {
|
|
119
|
+
const cleanup = armCall(reject, request.method, options, () => this.pending.delete(id));
|
|
120
|
+
this.pending.set(id, {
|
|
121
|
+
resolve: (response) => resolve(response),
|
|
122
|
+
reject,
|
|
123
|
+
cleanup
|
|
124
|
+
});
|
|
125
|
+
try {
|
|
126
|
+
this.child.stdin.write(`${JSON.stringify(request)}\n`);
|
|
127
|
+
} catch (cause) {
|
|
128
|
+
this.pending.delete(id);
|
|
129
|
+
cleanup();
|
|
130
|
+
const message = cause instanceof Error ? cause.message : String(cause);
|
|
131
|
+
reject(new McpTransportError(`MCP stdio transport failed to write request "${request.method}": ${message}`, {
|
|
132
|
+
type: "closed",
|
|
133
|
+
method: request.method,
|
|
134
|
+
cause
|
|
135
|
+
}));
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
async notify(method, params) {
|
|
140
|
+
if (this.closed) throw new McpTransportError("MCP stdio transport is closed.", {
|
|
141
|
+
type: "closed",
|
|
142
|
+
method
|
|
143
|
+
});
|
|
144
|
+
const notification = {
|
|
145
|
+
jsonrpc: JSONRPC_VERSION,
|
|
146
|
+
method,
|
|
147
|
+
params
|
|
148
|
+
};
|
|
149
|
+
this.child.stdin.write(`${JSON.stringify(notification)}\n`);
|
|
150
|
+
}
|
|
151
|
+
/** Allocate the next outbound request id. */
|
|
152
|
+
allocateId() {
|
|
153
|
+
return this.nextId++;
|
|
154
|
+
}
|
|
155
|
+
async close() {
|
|
156
|
+
if (this.closed) return;
|
|
157
|
+
this.closed = true;
|
|
158
|
+
this.reader.close();
|
|
159
|
+
this.failAll("closed", "transport closed by caller");
|
|
160
|
+
this.child.kill();
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
/**
|
|
164
|
+
* The Streamable HTTP transport — POSTs each JSON-RPC request to the
|
|
165
|
+
* server endpoint over the global `fetch` (Node 18+) and reads the single
|
|
166
|
+
* JSON response. No SSE-legacy, no WebSocket. Static `headers` (e.g. auth)
|
|
167
|
+
* are sent with every request.
|
|
168
|
+
*
|
|
169
|
+
* Constructed via {@link createHttpTransport}; the class itself is internal.
|
|
170
|
+
*/
|
|
171
|
+
var HttpTransport = class {
|
|
172
|
+
constructor(transport) {
|
|
173
|
+
this.nextId = 1;
|
|
174
|
+
this.url = transport.url;
|
|
175
|
+
this.headers = {
|
|
176
|
+
"content-type": "application/json",
|
|
177
|
+
accept: "application/json, text/event-stream",
|
|
178
|
+
...transport.headers
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
async request(request, options) {
|
|
182
|
+
const timeoutMs = options?.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
|
|
183
|
+
const controller = new AbortController();
|
|
184
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
185
|
+
const onAbort = () => controller.abort();
|
|
186
|
+
const signal = options?.signal;
|
|
187
|
+
if (signal) if (signal.aborted) controller.abort();
|
|
188
|
+
else signal.addEventListener("abort", onAbort, { once: true });
|
|
189
|
+
let response;
|
|
190
|
+
try {
|
|
191
|
+
response = await fetch(this.url, {
|
|
192
|
+
method: "POST",
|
|
193
|
+
headers: this.headers,
|
|
194
|
+
body: JSON.stringify(request),
|
|
195
|
+
signal: controller.signal
|
|
196
|
+
});
|
|
197
|
+
} catch (cause) {
|
|
198
|
+
const aborted = controller.signal.aborted;
|
|
199
|
+
const message = cause instanceof Error ? cause.message : String(cause);
|
|
200
|
+
throw new McpTransportError(aborted ? `MCP request "${request.method}" timed out or was aborted after ${timeoutMs}ms.` : `MCP http transport request "${request.method}" failed: ${message}`, {
|
|
201
|
+
type: aborted ? "timeout" : "connect",
|
|
202
|
+
method: request.method,
|
|
203
|
+
cause
|
|
204
|
+
});
|
|
205
|
+
} finally {
|
|
206
|
+
clearTimeout(timer);
|
|
207
|
+
if (signal) signal.removeEventListener("abort", onAbort);
|
|
208
|
+
}
|
|
209
|
+
if (!response.ok) throw new McpTransportError(`MCP http transport request "${request.method}" returned HTTP ${response.status}.`, {
|
|
210
|
+
type: "connect",
|
|
211
|
+
method: request.method,
|
|
212
|
+
context: { status: response.status }
|
|
213
|
+
});
|
|
214
|
+
return this.parseBody(response, request.method);
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Parse the HTTP response body into a JSON-RPC response. Streamable HTTP
|
|
218
|
+
* may answer with either `application/json` (a single response object)
|
|
219
|
+
* or `text/event-stream` (SSE frames); we read the body as text and
|
|
220
|
+
* extract the first JSON object, supporting the common `data: {...}`
|
|
221
|
+
* SSE line shape without a streaming parser.
|
|
222
|
+
*/
|
|
223
|
+
async parseBody(response, method) {
|
|
224
|
+
const raw = await response.text();
|
|
225
|
+
const jsonText = (response.headers.get("content-type")?.toLowerCase() ?? "").includes("text/event-stream") ? extractSseData(raw) : raw;
|
|
226
|
+
if (!jsonText) throw new McpTransportError(`MCP http transport got an empty response for "${method}".`, {
|
|
227
|
+
type: "protocol",
|
|
228
|
+
method
|
|
229
|
+
});
|
|
230
|
+
try {
|
|
231
|
+
return JSON.parse(jsonText);
|
|
232
|
+
} catch (cause) {
|
|
233
|
+
throw new McpTransportError(`MCP http transport got a non-JSON response for "${method}".`, {
|
|
234
|
+
type: "protocol",
|
|
235
|
+
method,
|
|
236
|
+
cause
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
async notify(method, params) {
|
|
241
|
+
const notification = {
|
|
242
|
+
jsonrpc: JSONRPC_VERSION,
|
|
243
|
+
method,
|
|
244
|
+
params
|
|
245
|
+
};
|
|
246
|
+
try {
|
|
247
|
+
await fetch(this.url, {
|
|
248
|
+
method: "POST",
|
|
249
|
+
headers: this.headers,
|
|
250
|
+
body: JSON.stringify(notification)
|
|
251
|
+
});
|
|
252
|
+
} catch (cause) {
|
|
253
|
+
throw new McpTransportError(`MCP http transport notification "${method}" failed: ${cause instanceof Error ? cause.message : String(cause)}`, {
|
|
254
|
+
type: "connect",
|
|
255
|
+
method,
|
|
256
|
+
cause
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
/** Allocate the next outbound request id. */
|
|
261
|
+
allocateId() {
|
|
262
|
+
return this.nextId++;
|
|
263
|
+
}
|
|
264
|
+
async close() {}
|
|
265
|
+
};
|
|
266
|
+
/**
|
|
267
|
+
* Pull the first `data:` JSON payload out of an SSE response body. MCP's
|
|
268
|
+
* Streamable HTTP transport answers a single request with one SSE frame
|
|
269
|
+
* carrying the JSON-RPC response; we take the first non-empty `data:`
|
|
270
|
+
* line. Returns an empty string when none is found.
|
|
271
|
+
*/
|
|
272
|
+
function extractSseData(body) {
|
|
273
|
+
for (const line of body.split(/\r?\n/)) {
|
|
274
|
+
const trimmed = line.trim();
|
|
275
|
+
if (trimmed.startsWith("data:")) {
|
|
276
|
+
const payload = trimmed.slice(5).trim();
|
|
277
|
+
if (payload && payload !== "[DONE]") return payload;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
return "";
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Build the concrete {@link McpTransportClient} for an {@link McpTransport}
|
|
284
|
+
* config — a {@link StdioTransport} for `type: "stdio"`, an
|
|
285
|
+
* {@link HttpTransport} for `type: "http"`. The returned client also
|
|
286
|
+
* carries an `allocateId()` for the JSON-RPC client to mint request ids.
|
|
287
|
+
*
|
|
288
|
+
* @param transport - The transport config (discriminated by `type`).
|
|
289
|
+
* @returns A transport client paired with its id allocator.
|
|
290
|
+
*/
|
|
291
|
+
function createTransport(transport) {
|
|
292
|
+
if (transport.type === "stdio") return new StdioTransport(transport);
|
|
293
|
+
return new HttpTransport(transport);
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* A minimal JSON-RPC 2.0 request/response client over any
|
|
297
|
+
* {@link McpTransportClient}. Mints monotonic ids, frames the
|
|
298
|
+
* `{ jsonrpc, id, method, params }` envelope, and unwraps the response —
|
|
299
|
+
* translating a JSON-RPC `error` member into a typed
|
|
300
|
+
* {@link McpTransportError} so callers branch on `error.type` rather than
|
|
301
|
+
* parsing the wire.
|
|
302
|
+
*
|
|
303
|
+
* Constructed via {@link createJsonRpcClient}; the class itself is internal.
|
|
304
|
+
*/
|
|
305
|
+
var JsonRpcClient = class {
|
|
306
|
+
constructor(transport) {
|
|
307
|
+
this.transport = transport;
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Issue a JSON-RPC `method` call and resolve with its `result`,
|
|
311
|
+
* throwing a typed {@link McpTransportError} on a JSON-RPC error member
|
|
312
|
+
* or a malformed response (neither `result` nor `error`).
|
|
313
|
+
*/
|
|
314
|
+
async call(method, params, options) {
|
|
315
|
+
const request = {
|
|
316
|
+
jsonrpc: JSONRPC_VERSION,
|
|
317
|
+
id: this.transport.allocateId(),
|
|
318
|
+
method,
|
|
319
|
+
params
|
|
320
|
+
};
|
|
321
|
+
const response = await this.transport.request(request, options);
|
|
322
|
+
if (response.error) throw new McpTransportError(`MCP "${method}" failed: ${response.error.message} (code ${response.error.code}).`, {
|
|
323
|
+
type: "protocol",
|
|
324
|
+
method,
|
|
325
|
+
context: { code: response.error.code },
|
|
326
|
+
cause: response.error.data
|
|
327
|
+
});
|
|
328
|
+
if (response.result === void 0) throw new McpTransportError(`MCP "${method}" returned a response with neither result nor error.`, {
|
|
329
|
+
type: "protocol",
|
|
330
|
+
method
|
|
331
|
+
});
|
|
332
|
+
return response.result;
|
|
333
|
+
}
|
|
334
|
+
/** Send a one-way JSON-RPC notification (no response awaited). */
|
|
335
|
+
notify(method, params) {
|
|
336
|
+
return this.transport.notify(method, params);
|
|
337
|
+
}
|
|
338
|
+
/** Close the underlying transport. */
|
|
339
|
+
close() {
|
|
340
|
+
return this.transport.close();
|
|
341
|
+
}
|
|
342
|
+
};
|
|
343
|
+
/**
|
|
344
|
+
* Build a {@link JsonRpcClientHandle} over a transport. Accepts either a
|
|
345
|
+
* pre-built {@link McpTransportClient} (the test seam — inject a scripted
|
|
346
|
+
* fake) or an {@link McpTransport} config, in which case the concrete
|
|
347
|
+
* transport is constructed via {@link createTransport}.
|
|
348
|
+
*
|
|
349
|
+
* When a bare {@link McpTransportClient} (without an `allocateId`) is
|
|
350
|
+
* injected, the client supplies its own monotonic id source.
|
|
351
|
+
*
|
|
352
|
+
* @param source - A transport client or an `McpTransport` config.
|
|
353
|
+
* @returns A JSON-RPC client handle.
|
|
354
|
+
*/
|
|
355
|
+
function createJsonRpcClient(source) {
|
|
356
|
+
return new JsonRpcClient(isTransportConfig(source) ? createTransport(source) : withIdAllocator(source));
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Distinguish an {@link McpTransport} config (a plain object with a `type`
|
|
360
|
+
* discriminator and no `request` method) from a built
|
|
361
|
+
* {@link McpTransportClient} (which exposes `request`).
|
|
362
|
+
*/
|
|
363
|
+
function isTransportConfig(source) {
|
|
364
|
+
return typeof source.request !== "function";
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Wrap an injected {@link McpTransportClient} that lacks its own
|
|
368
|
+
* `allocateId` with a monotonic id source, so the JSON-RPC client can mint
|
|
369
|
+
* request ids uniformly regardless of whether the transport was built here
|
|
370
|
+
* or supplied by a test.
|
|
371
|
+
*/
|
|
372
|
+
function withIdAllocator(client) {
|
|
373
|
+
const candidate = client;
|
|
374
|
+
if (typeof candidate.allocateId === "function") return candidate;
|
|
375
|
+
let nextId = 1;
|
|
376
|
+
return Object.assign(client, { allocateId: () => nextId++ });
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
//#endregion
|
|
380
|
+
export { createJsonRpcClient, createTransport };
|
|
381
|
+
//# sourceMappingURL=transport.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.mjs","names":[],"sources":["../../../../../../../@warlock.js/ai-tools/src/mcp/transport.ts"],"sourcesContent":["import { spawn, type ChildProcessWithoutNullStreams } from \"node:child_process\";\nimport { createInterface, type Interface } from \"node:readline\";\nimport type {\n JsonRpcId,\n JsonRpcRequest,\n JsonRpcResponse,\n McpTransport,\n} from \"../contracts\";\nimport { McpTransportError } from \"../errors\";\nimport type { McpTransportClient } from \"./transport.type\";\n\n/** Default per-request wait before a transport call is abandoned. */\nconst DEFAULT_REQUEST_TIMEOUT_MS = 30_000;\n\n/** The JSON-RPC version literal every outbound message carries. */\nconst JSONRPC_VERSION = \"2.0\";\n\n/**\n * A pending in-flight request awaiting its correlated response, keyed by\n * the JSON-RPC `id`. The stdio transport multiplexes many requests over\n * one line-framed pipe, so each resolve/reject is parked here until the\n * line whose `id` matches arrives.\n */\ninterface PendingCall {\n resolve(response: JsonRpcResponse): void;\n reject(error: McpTransportError): void;\n /** Clears the per-call timeout + abort wiring when the call settles. */\n cleanup(): void;\n}\n\n/**\n * Wire a per-call timeout and an optional caller `AbortSignal` onto a\n * pending request, returning a `cleanup()` that tears both down. The\n * `onSettle` callback removes the pending entry from whatever registry the\n * transport keeps so a late response can't double-settle.\n */\nfunction armCall(\n reject: (error: McpTransportError) => void,\n method: string,\n options: { signal?: AbortSignal; timeoutMs?: number } | undefined,\n onSettle: () => void,\n): () => void {\n const timeoutMs = options?.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;\n\n const timer = setTimeout(() => {\n onSettle();\n reject(\n new McpTransportError(\n `MCP request \"${method}\" timed out after ${timeoutMs}ms.`,\n { type: \"timeout\", method },\n ),\n );\n }, timeoutMs);\n\n const onAbort = () => {\n cleanup();\n reject(\n new McpTransportError(`MCP request \"${method}\" was aborted.`, {\n type: \"closed\",\n method,\n }),\n );\n };\n\n const signal = options?.signal;\n\n if (signal) {\n if (signal.aborted) {\n // Defer so the caller has the rejection wired before it fires.\n queueMicrotask(onAbort);\n } else {\n signal.addEventListener(\"abort\", onAbort, { once: true });\n }\n }\n\n function cleanup(): void {\n clearTimeout(timer);\n\n if (signal) {\n signal.removeEventListener(\"abort\", onAbort);\n }\n }\n\n return cleanup;\n}\n\n/**\n * The stdio transport — spawns a child process and speaks JSON-RPC over\n * its stdin/stdout, one JSON object per line (newline-delimited framing).\n * Uses only Node built-ins (`node:child_process` + `node:readline`); no\n * dependency.\n *\n * Constructed via {@link createStdioTransport}; the class itself is\n * internal.\n */\nclass StdioTransport implements McpTransportClient {\n /** The spawned server process. */\n private readonly child: ChildProcessWithoutNullStreams;\n\n /** Line reader over the child's stdout — one JSON-RPC message per line. */\n private readonly reader: Interface;\n\n /** In-flight requests awaiting a correlated response, keyed by id. */\n private readonly pending = new Map<JsonRpcId, PendingCall>();\n\n /** Monotonic id source for outbound requests. */\n private nextId = 1;\n\n /** Flipped once {@link close} runs (or the child exits) so reuse rejects. */\n private closed = false;\n\n public constructor(transport: Extract<McpTransport, { type: \"stdio\" }>) {\n let child: ChildProcessWithoutNullStreams;\n\n try {\n child = spawn(transport.command, transport.args ?? [], {\n // process.env is NOT inherited unless the caller opts in — pass\n // what the server needs explicitly, mirroring the workspace shell\n // policy. `undefined` lets Node default to an empty-ish env.\n env: transport.env,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n }) as ChildProcessWithoutNullStreams;\n } catch (cause) {\n const message = cause instanceof Error ? cause.message : String(cause);\n\n throw new McpTransportError(\n `MCP stdio transport could not spawn \"${transport.command}\": ${message}`,\n { type: \"connect\", cause },\n );\n }\n\n this.child = child;\n this.reader = createInterface({ input: child.stdout });\n\n this.reader.on(\"line\", (line) => this.onLine(line));\n\n // A child that dies takes every in-flight (and future) call with it.\n child.on(\"exit\", (code) => this.failAll(\"connect\", `child exited with code ${code ?? \"null\"}`));\n child.on(\"error\", (error) => this.failAll(\"connect\", error.message));\n }\n\n /**\n * Parse one stdout line and route it to its pending request. Non-JSON\n * lines (a server logging to stdout) and messages with no matching `id`\n * (notifications, stray responses) are ignored — robustness over strictness.\n */\n private onLine(line: string): void {\n const trimmed = line.trim();\n\n if (!trimmed) {\n return;\n }\n\n let message: JsonRpcResponse;\n\n try {\n message = JSON.parse(trimmed) as JsonRpcResponse;\n } catch {\n // Not a JSON-RPC line (server diagnostics on stdout) — ignore.\n return;\n }\n\n if (message.id === undefined || message.id === null) {\n // A notification or a malformed response — nothing to correlate.\n return;\n }\n\n const call = this.pending.get(message.id);\n\n if (!call) {\n return;\n }\n\n this.pending.delete(message.id);\n call.cleanup();\n call.resolve(message);\n }\n\n /**\n * Reject every pending call (and mark the transport unusable) when the\n * child dies or errors — so a hung server can never leave a caller\n * waiting forever.\n */\n private failAll(type: \"connect\" | \"closed\", reason: string): void {\n this.closed = true;\n\n for (const [id, call] of this.pending) {\n this.pending.delete(id);\n call.cleanup();\n call.reject(\n new McpTransportError(`MCP stdio transport failed: ${reason}.`, { type }),\n );\n }\n }\n\n public request<TResult = unknown>(\n request: JsonRpcRequest,\n options?: { signal?: AbortSignal; timeoutMs?: number },\n ): Promise<JsonRpcResponse<TResult>> {\n if (this.closed) {\n return Promise.reject(\n new McpTransportError(\"MCP stdio transport is closed.\", {\n type: \"closed\",\n method: request.method,\n }),\n );\n }\n\n const id = request.id;\n\n return new Promise<JsonRpcResponse<TResult>>((resolve, reject) => {\n const cleanup = armCall(reject, request.method, options, () =>\n this.pending.delete(id),\n );\n\n this.pending.set(id, {\n resolve: (response) => resolve(response as JsonRpcResponse<TResult>),\n reject,\n cleanup,\n });\n\n try {\n this.child.stdin.write(`${JSON.stringify(request)}\\n`);\n } catch (cause) {\n this.pending.delete(id);\n cleanup();\n\n const message = cause instanceof Error ? cause.message : String(cause);\n\n reject(\n new McpTransportError(\n `MCP stdio transport failed to write request \"${request.method}\": ${message}`,\n { type: \"closed\", method: request.method, cause },\n ),\n );\n }\n });\n }\n\n public async notify(method: string, params?: unknown): Promise<void> {\n if (this.closed) {\n throw new McpTransportError(\"MCP stdio transport is closed.\", {\n type: \"closed\",\n method,\n });\n }\n\n const notification = { jsonrpc: JSONRPC_VERSION, method, params };\n this.child.stdin.write(`${JSON.stringify(notification)}\\n`);\n }\n\n /** Allocate the next outbound request id. */\n public allocateId(): number {\n return this.nextId++;\n }\n\n public async close(): Promise<void> {\n if (this.closed) {\n return;\n }\n\n this.closed = true;\n this.reader.close();\n this.failAll(\"closed\", \"transport closed by caller\");\n this.child.kill();\n }\n}\n\n/**\n * The Streamable HTTP transport — POSTs each JSON-RPC request to the\n * server endpoint over the global `fetch` (Node 18+) and reads the single\n * JSON response. No SSE-legacy, no WebSocket. Static `headers` (e.g. auth)\n * are sent with every request.\n *\n * Constructed via {@link createHttpTransport}; the class itself is internal.\n */\nclass HttpTransport implements McpTransportClient {\n /** The server endpoint POST target. */\n private readonly url: string;\n\n /** Static headers merged into every request (auth, etc.). */\n private readonly headers: Record<string, string>;\n\n /** Monotonic id source for outbound requests. */\n private nextId = 1;\n\n public constructor(transport: Extract<McpTransport, { type: \"http\" }>) {\n this.url = transport.url;\n this.headers = {\n \"content-type\": \"application/json\",\n accept: \"application/json, text/event-stream\",\n ...transport.headers,\n };\n }\n\n public async request<TResult = unknown>(\n request: JsonRpcRequest,\n options?: { signal?: AbortSignal; timeoutMs?: number },\n ): Promise<JsonRpcResponse<TResult>> {\n const timeoutMs = options?.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n const onAbort = () => controller.abort();\n const signal = options?.signal;\n\n if (signal) {\n if (signal.aborted) {\n controller.abort();\n } else {\n signal.addEventListener(\"abort\", onAbort, { once: true });\n }\n }\n\n let response: Response;\n\n try {\n response = await fetch(this.url, {\n method: \"POST\",\n headers: this.headers,\n body: JSON.stringify(request),\n signal: controller.signal,\n });\n } catch (cause) {\n const aborted = controller.signal.aborted;\n const message = cause instanceof Error ? cause.message : String(cause);\n\n throw new McpTransportError(\n aborted\n ? `MCP request \"${request.method}\" timed out or was aborted after ${timeoutMs}ms.`\n : `MCP http transport request \"${request.method}\" failed: ${message}`,\n { type: aborted ? \"timeout\" : \"connect\", method: request.method, cause },\n );\n } finally {\n clearTimeout(timer);\n\n if (signal) {\n signal.removeEventListener(\"abort\", onAbort);\n }\n }\n\n if (!response.ok) {\n throw new McpTransportError(\n `MCP http transport request \"${request.method}\" returned HTTP ${response.status}.`,\n { type: \"connect\", method: request.method, context: { status: response.status } },\n );\n }\n\n return this.parseBody<TResult>(response, request.method);\n }\n\n /**\n * Parse the HTTP response body into a JSON-RPC response. Streamable HTTP\n * may answer with either `application/json` (a single response object)\n * or `text/event-stream` (SSE frames); we read the body as text and\n * extract the first JSON object, supporting the common `data: {...}`\n * SSE line shape without a streaming parser.\n */\n private async parseBody<TResult>(\n response: Response,\n method: string,\n ): Promise<JsonRpcResponse<TResult>> {\n const raw = await response.text();\n const contentType = response.headers.get(\"content-type\")?.toLowerCase() ?? \"\";\n\n const jsonText = contentType.includes(\"text/event-stream\")\n ? extractSseData(raw)\n : raw;\n\n if (!jsonText) {\n throw new McpTransportError(\n `MCP http transport got an empty response for \"${method}\".`,\n { type: \"protocol\", method },\n );\n }\n\n try {\n return JSON.parse(jsonText) as JsonRpcResponse<TResult>;\n } catch (cause) {\n throw new McpTransportError(\n `MCP http transport got a non-JSON response for \"${method}\".`,\n { type: \"protocol\", method, cause },\n );\n }\n }\n\n public async notify(method: string, params?: unknown): Promise<void> {\n const notification = { jsonrpc: JSONRPC_VERSION, method, params };\n\n // A notification expects no response; fire-and-forget but surface a\n // connect failure so a dead endpoint is not silently ignored.\n try {\n await fetch(this.url, {\n method: \"POST\",\n headers: this.headers,\n body: JSON.stringify(notification),\n });\n } catch (cause) {\n const message = cause instanceof Error ? cause.message : String(cause);\n\n throw new McpTransportError(\n `MCP http transport notification \"${method}\" failed: ${message}`,\n { type: \"connect\", method, cause },\n );\n }\n }\n\n /** Allocate the next outbound request id. */\n public allocateId(): number {\n return this.nextId++;\n }\n\n public async close(): Promise<void> {\n // Streamable HTTP is stateless per request — nothing persistent to\n // release.\n }\n}\n\n/**\n * Pull the first `data:` JSON payload out of an SSE response body. MCP's\n * Streamable HTTP transport answers a single request with one SSE frame\n * carrying the JSON-RPC response; we take the first non-empty `data:`\n * line. Returns an empty string when none is found.\n */\nfunction extractSseData(body: string): string {\n for (const line of body.split(/\\r?\\n/)) {\n const trimmed = line.trim();\n\n if (trimmed.startsWith(\"data:\")) {\n const payload = trimmed.slice(\"data:\".length).trim();\n\n if (payload && payload !== \"[DONE]\") {\n return payload;\n }\n }\n }\n\n return \"\";\n}\n\n/**\n * Build the concrete {@link McpTransportClient} for an {@link McpTransport}\n * config — a {@link StdioTransport} for `type: \"stdio\"`, an\n * {@link HttpTransport} for `type: \"http\"`. The returned client also\n * carries an `allocateId()` for the JSON-RPC client to mint request ids.\n *\n * @param transport - The transport config (discriminated by `type`).\n * @returns A transport client paired with its id allocator.\n */\nexport function createTransport(\n transport: McpTransport,\n): McpTransportClient & { allocateId(): number } {\n if (transport.type === \"stdio\") {\n return new StdioTransport(transport);\n }\n\n return new HttpTransport(transport);\n}\n\n/**\n * A minimal JSON-RPC 2.0 request/response client over any\n * {@link McpTransportClient}. Mints monotonic ids, frames the\n * `{ jsonrpc, id, method, params }` envelope, and unwraps the response —\n * translating a JSON-RPC `error` member into a typed\n * {@link McpTransportError} so callers branch on `error.type` rather than\n * parsing the wire.\n *\n * Constructed via {@link createJsonRpcClient}; the class itself is internal.\n */\nclass JsonRpcClient {\n /** The underlying framing transport. */\n private readonly transport: McpTransportClient & { allocateId(): number };\n\n public constructor(transport: McpTransportClient & { allocateId(): number }) {\n this.transport = transport;\n }\n\n /**\n * Issue a JSON-RPC `method` call and resolve with its `result`,\n * throwing a typed {@link McpTransportError} on a JSON-RPC error member\n * or a malformed response (neither `result` nor `error`).\n */\n public async call<TResult = unknown>(\n method: string,\n params?: unknown,\n options?: { signal?: AbortSignal; timeoutMs?: number },\n ): Promise<TResult> {\n const request: JsonRpcRequest = {\n jsonrpc: JSONRPC_VERSION,\n id: this.transport.allocateId(),\n method,\n params,\n };\n\n const response = await this.transport.request<TResult>(request, options);\n\n if (response.error) {\n throw new McpTransportError(\n `MCP \"${method}\" failed: ${response.error.message} (code ${response.error.code}).`,\n { type: \"protocol\", method, context: { code: response.error.code }, cause: response.error.data },\n );\n }\n\n if (response.result === undefined) {\n throw new McpTransportError(\n `MCP \"${method}\" returned a response with neither result nor error.`,\n { type: \"protocol\", method },\n );\n }\n\n return response.result;\n }\n\n /** Send a one-way JSON-RPC notification (no response awaited). */\n public notify(method: string, params?: unknown): Promise<void> {\n return this.transport.notify(method, params);\n }\n\n /** Close the underlying transport. */\n public close(): Promise<void> {\n return this.transport.close();\n }\n}\n\n/**\n * A JSON-RPC client over an MCP transport. Either pass an already-built\n * transport client (tests inject a fake) or an {@link McpTransport} config\n * to spawn/connect a real one.\n */\nexport interface JsonRpcClientHandle {\n /** Issue a request and resolve with its `result` (throws on error). */\n call<TResult = unknown>(\n method: string,\n params?: unknown,\n options?: { signal?: AbortSignal; timeoutMs?: number },\n ): Promise<TResult>;\n /** Send a one-way notification. */\n notify(method: string, params?: unknown): Promise<void>;\n /** Close the underlying transport. */\n close(): Promise<void>;\n}\n\n/**\n * Build a {@link JsonRpcClientHandle} over a transport. Accepts either a\n * pre-built {@link McpTransportClient} (the test seam — inject a scripted\n * fake) or an {@link McpTransport} config, in which case the concrete\n * transport is constructed via {@link createTransport}.\n *\n * When a bare {@link McpTransportClient} (without an `allocateId`) is\n * injected, the client supplies its own monotonic id source.\n *\n * @param source - A transport client or an `McpTransport` config.\n * @returns A JSON-RPC client handle.\n */\nexport function createJsonRpcClient(\n source: McpTransport | McpTransportClient,\n): JsonRpcClientHandle {\n const transport: McpTransportClient & { allocateId(): number } = isTransportConfig(source)\n ? createTransport(source)\n : withIdAllocator(source);\n\n return new JsonRpcClient(transport);\n}\n\n/**\n * Distinguish an {@link McpTransport} config (a plain object with a `type`\n * discriminator and no `request` method) from a built\n * {@link McpTransportClient} (which exposes `request`).\n */\nfunction isTransportConfig(\n source: McpTransport | McpTransportClient,\n): source is McpTransport {\n return typeof (source as McpTransportClient).request !== \"function\";\n}\n\n/**\n * Wrap an injected {@link McpTransportClient} that lacks its own\n * `allocateId` with a monotonic id source, so the JSON-RPC client can mint\n * request ids uniformly regardless of whether the transport was built here\n * or supplied by a test.\n */\nfunction withIdAllocator(\n client: McpTransportClient,\n): McpTransportClient & { allocateId(): number } {\n const candidate = client as McpTransportClient & { allocateId?(): number };\n\n if (typeof candidate.allocateId === \"function\") {\n return candidate as McpTransportClient & { allocateId(): number };\n }\n\n let nextId = 1;\n\n return Object.assign(client, { allocateId: () => nextId++ });\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { JsonRpcRequest, JsonRpcResponse } from "../contracts/mcp.type.mjs";
|
|
2
|
+
//#region ../@warlock.js/ai-tools/src/mcp/transport.type.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Internal contract every concrete MCP transport (stdio / Streamable HTTP)
|
|
5
|
+
* satisfies. Pure declaration — the factories that build transports live
|
|
6
|
+
* in `transport.ts`.
|
|
7
|
+
*
|
|
8
|
+
* A transport is a thin, framing-only layer: it ships one JSON-RPC request
|
|
9
|
+
* out and resolves with the matching response, and it can ship a one-way
|
|
10
|
+
* notification (no response expected). It owns nothing protocol-specific —
|
|
11
|
+
* the `initialize` handshake, `tools/list`, and `tools/call` semantics all
|
|
12
|
+
* live above it in {@link import("./client").mcp}.
|
|
13
|
+
*
|
|
14
|
+
* **`type`, never `kind`.** This package's discriminators are all `type`;
|
|
15
|
+
* any inbound MCP `kind` is translated at the client boundary.
|
|
16
|
+
*/
|
|
17
|
+
interface McpTransportClient {
|
|
18
|
+
/**
|
|
19
|
+
* Send a JSON-RPC request and resolve with its matching response.
|
|
20
|
+
*
|
|
21
|
+
* The transport correlates the response by `id`; on a stdio transport
|
|
22
|
+
* that means matching the line whose `id` equals the request's, on HTTP
|
|
23
|
+
* it is the single response to the POST. Honors `signal` to abort an
|
|
24
|
+
* in-flight call (rejecting the returned promise) and `timeoutMs` to
|
|
25
|
+
* bound the wait.
|
|
26
|
+
*
|
|
27
|
+
* @param request - A fully-formed JSON-RPC request (caller assigns `id`).
|
|
28
|
+
* @param options - Optional per-call abort signal and timeout.
|
|
29
|
+
*/
|
|
30
|
+
request<TResult = unknown>(request: JsonRpcRequest, options?: {
|
|
31
|
+
signal?: AbortSignal;
|
|
32
|
+
timeoutMs?: number;
|
|
33
|
+
}): Promise<JsonRpcResponse<TResult>>;
|
|
34
|
+
/**
|
|
35
|
+
* Send a JSON-RPC notification — a method call with no `id` that
|
|
36
|
+
* expects no response (e.g. the post-handshake `notifications/initialized`).
|
|
37
|
+
*
|
|
38
|
+
* @param method - The notification method name.
|
|
39
|
+
* @param params - Optional method parameters.
|
|
40
|
+
*/
|
|
41
|
+
notify(method: string, params?: unknown): Promise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* Close the transport, releasing its resources — kill the spawned child
|
|
44
|
+
* (stdio) or drop the session (http). Idempotent: closing twice is a
|
|
45
|
+
* no-op.
|
|
46
|
+
*/
|
|
47
|
+
close(): Promise<void>;
|
|
48
|
+
}
|
|
49
|
+
//#endregion
|
|
50
|
+
export { McpTransportClient };
|
|
51
|
+
//# sourceMappingURL=transport.type.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.type.d.mts","names":[],"sources":["../../../../../../../@warlock.js/ai-tools/src/mcp/transport.type.ts"],"mappings":";;;;;AAgBA;;;;;;;;;;;UAAiB,kBAAA;EAaf;;;;;;;;;;;;EAAA,OAAA,oBACE,OAAA,EAAS,cAAA,EACT,OAAA;IAAY,MAAA,GAAS,WAAA;IAAa,SAAA;EAAA,IACjC,OAAA,CAAQ,eAAA,CAAgB,OAAA;EAgBlB;;AAAO;;;;;EAPhB,MAAA,CAAO,MAAA,UAAgB,MAAA,aAAmB,OAAA;;;;;;EAO1C,KAAA,IAAS,OAAA;AAAA"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
//#region ../@warlock.js/node_modules/@standard-schema/spec/dist/index.d.ts
|
|
2
|
+
/** The Standard Typed interface. This is a base type extended by other specs. */
|
|
3
|
+
interface StandardTypedV1<Input = unknown, Output = Input> {
|
|
4
|
+
/** The Standard properties. */
|
|
5
|
+
readonly "~standard": StandardTypedV1.Props<Input, Output>;
|
|
6
|
+
}
|
|
7
|
+
declare namespace StandardTypedV1 {
|
|
8
|
+
/** The Standard Typed properties interface. */
|
|
9
|
+
interface Props<Input = unknown, Output = Input> {
|
|
10
|
+
/** The version number of the standard. */
|
|
11
|
+
readonly version: 1;
|
|
12
|
+
/** The vendor name of the schema library. */
|
|
13
|
+
readonly vendor: string;
|
|
14
|
+
/** Inferred types associated with the schema. */
|
|
15
|
+
readonly types?: Types<Input, Output> | undefined;
|
|
16
|
+
}
|
|
17
|
+
/** The Standard Typed types interface. */
|
|
18
|
+
interface Types<Input = unknown, Output = Input> {
|
|
19
|
+
/** The input type of the schema. */
|
|
20
|
+
readonly input: Input;
|
|
21
|
+
/** The output type of the schema. */
|
|
22
|
+
readonly output: Output;
|
|
23
|
+
}
|
|
24
|
+
/** Infers the input type of a Standard Typed. */
|
|
25
|
+
type InferInput<Schema extends StandardTypedV1> = NonNullable<Schema["~standard"]["types"]>["input"];
|
|
26
|
+
/** Infers the output type of a Standard Typed. */
|
|
27
|
+
type InferOutput<Schema extends StandardTypedV1> = NonNullable<Schema["~standard"]["types"]>["output"];
|
|
28
|
+
}
|
|
29
|
+
/** The Standard Schema interface. */
|
|
30
|
+
interface StandardSchemaV1<Input = unknown, Output = Input> {
|
|
31
|
+
/** The Standard Schema properties. */
|
|
32
|
+
readonly "~standard": StandardSchemaV1.Props<Input, Output>;
|
|
33
|
+
}
|
|
34
|
+
declare namespace StandardSchemaV1 {
|
|
35
|
+
/** The Standard Schema properties interface. */
|
|
36
|
+
interface Props<Input = unknown, Output = Input> extends StandardTypedV1.Props<Input, Output> {
|
|
37
|
+
/** Validates unknown input values. */
|
|
38
|
+
readonly validate: (value: unknown, options?: StandardSchemaV1.Options | undefined) => Result<Output> | Promise<Result<Output>>;
|
|
39
|
+
}
|
|
40
|
+
/** The result interface of the validate function. */
|
|
41
|
+
type Result<Output> = SuccessResult<Output> | FailureResult;
|
|
42
|
+
/** The result interface if validation succeeds. */
|
|
43
|
+
interface SuccessResult<Output> {
|
|
44
|
+
/** The typed output value. */
|
|
45
|
+
readonly value: Output;
|
|
46
|
+
/** A falsy value for `issues` indicates success. */
|
|
47
|
+
readonly issues?: undefined;
|
|
48
|
+
}
|
|
49
|
+
interface Options {
|
|
50
|
+
/** Explicit support for additional vendor-specific parameters, if needed. */
|
|
51
|
+
readonly libraryOptions?: Record<string, unknown> | undefined;
|
|
52
|
+
}
|
|
53
|
+
/** The result interface if validation fails. */
|
|
54
|
+
interface FailureResult {
|
|
55
|
+
/** The issues of failed validation. */
|
|
56
|
+
readonly issues: ReadonlyArray<Issue>;
|
|
57
|
+
}
|
|
58
|
+
/** The issue interface of the failure output. */
|
|
59
|
+
interface Issue {
|
|
60
|
+
/** The error message of the issue. */
|
|
61
|
+
readonly message: string;
|
|
62
|
+
/** The path of the issue, if any. */
|
|
63
|
+
readonly path?: ReadonlyArray<PropertyKey | PathSegment> | undefined;
|
|
64
|
+
}
|
|
65
|
+
/** The path segment interface of the issue. */
|
|
66
|
+
interface PathSegment {
|
|
67
|
+
/** The key representing a path segment. */
|
|
68
|
+
readonly key: PropertyKey;
|
|
69
|
+
}
|
|
70
|
+
/** The Standard types interface. */
|
|
71
|
+
interface Types<Input = unknown, Output = Input> extends StandardTypedV1.Types<Input, Output> {}
|
|
72
|
+
/** Infers the input type of a Standard. */
|
|
73
|
+
type InferInput<Schema extends StandardTypedV1> = StandardTypedV1.InferInput<Schema>;
|
|
74
|
+
/** Infers the output type of a Standard. */
|
|
75
|
+
type InferOutput<Schema extends StandardTypedV1> = StandardTypedV1.InferOutput<Schema>;
|
|
76
|
+
}
|
|
77
|
+
/** The Standard JSON Schema interface. */
|
|
78
|
+
//#endregion
|
|
79
|
+
export { StandardSchemaV1 };
|
|
80
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":["Input","Output","StandardTypedV1","Props","version","vendor","types","Types","input","output","InferInput","Schema","NonNullable","InferOutput","StandardSchemaV1","validate","value","Options","options","Result","Promise","SuccessResult","FailureResult","issues","libraryOptions","Record","ReadonlyArray","Issue","message","path","PropertyKey","PathSegment","key","StandardJSONSchemaV1","jsonSchema","Converter","Target","target"],"sources":["../../../../../../../../../../@warlock.js/node_modules/@standard-schema/spec/dist/index.d.ts"],"x_google_ignoreList":[0],"mappings":";;UACU,eAAA,2BAA0C,KAAA;EAA3B;EAAA,SAEZ,WAAA,EAAa,eAAA,CAAgB,KAAA,CAAM,KAAA,EAAO,MAAA;AAAA;AAAA,kBAErC,eAAA;EAFqC;EAAA,UAIzCG,KAAAA,2BAAgC,KAAA;IAJC;IAAA,SAM9BC,OAAAA;IARSJ;IAAAA,SAUTK,MAAAA;IAVmCL;IAAAA,SAYnCM,KAAAA,GAAQ,KAAA,CAAM,KAAA,EAAO,MAAA;EAAA;EAVIH;EAAAA,UAa5BI,KAAAA,2BAAgC,KAAA;IAbSN;IAAAA,SAetCO,KAAAA,EAAO,KAAA;IAfqC;IAAA,SAiB5CC,MAAAA,EAAQ,MAAA;EAAA;EAfQ;EAAA,KAkBxBC,UAAAA,gBAA0B,eAAA,IAAmB,WAAA,CAAY,MAAA;EAVnC;EAAA,KAYtBG,WAAAA,gBAA2B,eAAA,IAAmB,WAAA,CAAY,MAAA;AAAA;;UAGzD,gBAAA,2BAA2C,KAAA;EAR5B;EAAA,SAUZ,WAAA,EAAa,gBAAA,CAAiB,KAAA,CAAM,KAAA,EAAO,MAAA;AAAA;AAAA,kBAEtC,gBAAA;EAPkB;EAAA,UAStBV,KAAAA,2BAAgC,KAAA,UAAe,eAAA,CAAgB,KAAA,CAAM,KAAA,EAAO,MAAA;IATnC;IAAA,SAWtCY,QAAAA,GAAWC,KAAAA,WAAgBE,OAAAA,GAAU,gBAAA,CAAiB,OAAA,iBAAwB,MAAA,CAAO,MAAA,IAAU,OAAA,CAAQ,MAAA,CAAO,MAAA;EAAA;EA7BjHf;EAAAA,KAgCLgB,MAAAA,WAAiB,aAAA,CAAc,MAAA,IAAU,aAAA;EAhCblB;EAAAA,UAkCvBoB,aAAAA;IAhCGjB;IAAAA,SAkCAY,KAAAA,EAAO,MAAA;IA9BPV;IAAAA,SAgCAiB,MAAAA;EAAAA;EAAAA,UAEHN,OAAAA;IA/BAV;IAAAA,SAiCGiB,cAAAA,GAAiB,MAAA;EAAA;EAjCYxB;EAAAA,UAoChCsB,aAAAA;IAlCUtB;IAAAA,SAoCPuB,MAAAA,EAAQ,aAAA,CAAc,KAAA;EAAA;EA/B9Bb;EAAAA,UAkCKiB,KAAAA;IAlCqBzB;IAAAA,SAoClB0B,OAAAA;IApCiDjB;IAAAA,SAsCjDkB,IAAAA,GAAO,aAAA,CAAc,WAAA,GAAc,WAAA;EAAA;EApChB3B;EAAAA,UAuCtB6B,WAAAA;IAvCqDpB;IAAAA,SAyClDqB,GAAAA,EAAK,WAAA;EAAA;EAtCZ;EAAA,UAyCIzB,KAAAA,2BAAgC,KAAA,UAAe,eAAA,CAAgB,KAAA,CAAM,KAAA,EAAO,MAAA;EAzCrC;EAAA,KA4C5CG,UAAAA,gBAA0B,eAAA,IAAmB,eAAA,CAAgB,UAAA,CAAW,MAAA;EA1CzB;EAAA,KA4C/CG,WAAAA,gBAA2B,eAAA,IAAmB,eAAA,CAAgB,WAAA,CAAY,MAAA;AAAA"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { FetchUrlInput, FetchUrlOptions, FetchUrlResult, WebSearchInput, WebSearchOptions, WebSearchResult } from "./contracts/web.type.mjs";
|
|
2
|
+
import { HttpRequestInput, HttpRequestOptions, HttpRequestResult } from "./contracts/http.type.mjs";
|
|
3
|
+
import { CalculatorInput, CalculatorOptions, CalculatorResult, DateTimeInput, DateTimeOptions, DateTimeResult } from "./contracts/utility.type.mjs";
|
|
4
|
+
import { McpFactory } from "./mcp/index.mjs";
|
|
5
|
+
import { ToolContract } from "@warlock.js/ai";
|
|
6
|
+
|
|
7
|
+
//#region ../@warlock.js/ai-tools/src/register.d.ts
|
|
8
|
+
/**
|
|
9
|
+
* The `ai.tools.*` namespace — the five ready-made agent tools this
|
|
10
|
+
* package vends. Each member is a factory returning a {@link ToolContract}
|
|
11
|
+
* that drops straight into `ai.agent({ tools: [...] })`. Declared inline on
|
|
12
|
+
* the `Ai` interface below (one block, one shape) rather than accreted
|
|
13
|
+
* across the tool sub-barrels, mirroring the `ai.workspace` augmentation in
|
|
14
|
+
* `@warlock.js/ai-workspace`.
|
|
15
|
+
*/
|
|
16
|
+
interface AiToolsNamespace {
|
|
17
|
+
/** Search the web via a chosen provider; returns ranked LLM-ready hits. */
|
|
18
|
+
webSearch(options: WebSearchOptions): ToolContract<WebSearchInput, WebSearchResult>;
|
|
19
|
+
/** Fetch a URL (host-allowlisted, byte-capped) and return its content. */
|
|
20
|
+
fetchUrl(options?: FetchUrlOptions): ToolContract<FetchUrlInput, FetchUrlResult>;
|
|
21
|
+
/** A guarded HTTP/REST client — method + host allowlists, byte/timeout caps. */
|
|
22
|
+
http(options?: HttpRequestOptions): ToolContract<HttpRequestInput, HttpRequestResult>;
|
|
23
|
+
/** A SAFE arithmetic-expression evaluator (no `eval`/`Function`). */
|
|
24
|
+
calculator(options?: CalculatorOptions): ToolContract<CalculatorInput, CalculatorResult>;
|
|
25
|
+
/** Clock/calendar ops — now / add / diff / format over ISO instants. */
|
|
26
|
+
dateTime(options?: DateTimeOptions): ToolContract<DateTimeInput, DateTimeResult>;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Attach the `tools` namespace and the `mcp` factory to the `ai` namespace
|
|
30
|
+
* via module augmentation, per the `ai.`-namespace convention.
|
|
31
|
+
* `@warlock.js/ai` now exposes a named `Ai` interface for exactly this, so
|
|
32
|
+
* after a bare `import "@warlock.js/ai-tools"`, `ai.tools.webSearch(...)`,
|
|
33
|
+
* `ai.tools.http(...)`, `ai.mcp(server)`, and `ai.mcp.serve(source)` are all
|
|
34
|
+
* globally typed — no view/cast needed.
|
|
35
|
+
*/
|
|
36
|
+
declare module "@warlock.js/ai" {
|
|
37
|
+
interface Ai {
|
|
38
|
+
/**
|
|
39
|
+
* Ready-made agent tools from `@warlock.js/ai-tools` — web search,
|
|
40
|
+
* fetch/scrape, HTTP/REST, calculator, and date-time. Each returns a
|
|
41
|
+
* `ToolContract` that slots into `ai.agent({ tools: [...] })`.
|
|
42
|
+
*/
|
|
43
|
+
tools: AiToolsNamespace;
|
|
44
|
+
/**
|
|
45
|
+
* The Model Context Protocol surface — `ai.mcp(server)` connects to an
|
|
46
|
+
* external MCP server and adapts its tools as agent tools (Direction A),
|
|
47
|
+
* while `ai.mcp.serve(source, options)` exposes a local primitive AS an
|
|
48
|
+
* MCP server other clients can consume (Direction B).
|
|
49
|
+
*/
|
|
50
|
+
mcp: McpFactory;
|
|
51
|
+
}
|
|
52
|
+
} //# sourceMappingURL=register.d.ts.map
|
|
53
|
+
//#endregion
|
|
54
|
+
export { AiToolsNamespace };
|
|
55
|
+
//# sourceMappingURL=register.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register.d.mts","names":[],"sources":["../../../../../../@warlock.js/ai-tools/src/register.ts"],"mappings":";;;;;;;;;;;;AAiCA;;;UAAiB,gBAAA;EAEoC;EAAnD,SAAA,CAAU,OAAA,EAAS,gBAAA,GAAmB,YAAA,CAAa,cAAA,EAAgB,eAAA;EAA7B;EAEtC,QAAA,CAAS,OAAA,GAAU,eAAA,GAAkB,YAAA,CAAa,aAAA,EAAe,cAAA;EAAf;EAElD,IAAA,CAAK,OAAA,GAAU,kBAAA,GAAqB,YAAA,CAAa,gBAAA,EAAkB,iBAAA;EAF9B;EAIrC,UAAA,CAAW,OAAA,GAAU,iBAAA,GAAoB,YAAA,CAAa,eAAA,EAAiB,gBAAA;EAFtB;EAIjD,QAAA,CAAS,OAAA,GAAU,eAAA,GAAkB,YAAA,CAAa,aAAA,EAAe,cAAA;AAAA;;;;;;;;;;YAYvD,EAAA;IApBV;;;;;IA0BE,KAAA,EAAO,gBAAA;IAxBT;;;;;;IA+BE,GAAA,EAAK,UAAU;EAAA;AAAA"}
|
package/esm/register.mjs
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { httpRequestTool } from "./http/http-request.mjs";
|
|
2
|
+
import { mcp } from "./mcp/index.mjs";
|
|
3
|
+
import { calculatorTool } from "./utility/calculator.mjs";
|
|
4
|
+
import { dateTimeTool } from "./utility/date-time.mjs";
|
|
5
|
+
import { fetchUrlTool } from "./web/fetch-url.mjs";
|
|
6
|
+
import { webSearchTool } from "./web/web-search.mjs";
|
|
7
|
+
import { ai } from "@warlock.js/ai";
|
|
8
|
+
|
|
9
|
+
//#region ../@warlock.js/ai-tools/src/register.ts
|
|
10
|
+
ai.tools = {
|
|
11
|
+
webSearch: webSearchTool,
|
|
12
|
+
fetchUrl: fetchUrlTool,
|
|
13
|
+
http: httpRequestTool,
|
|
14
|
+
calculator: calculatorTool,
|
|
15
|
+
dateTime: (options) => dateTimeTool(options)
|
|
16
|
+
};
|
|
17
|
+
ai.mcp = mcp;
|
|
18
|
+
|
|
19
|
+
//#endregion
|
|
20
|
+
export { };
|
|
21
|
+
//# sourceMappingURL=register.mjs.map
|