reasonix 0.11.2 → 0.11.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +342 -10
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +86 -10
- package/dist/index.js +159 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -70,6 +70,29 @@ function addProjectShellAllowed(rootDir, prefix, path5 = defaultConfigPath()) {
|
|
|
70
70
|
cfg.projects[rootDir].shellAllowed = [...existing, trimmed];
|
|
71
71
|
writeConfig(cfg, path5);
|
|
72
72
|
}
|
|
73
|
+
function removeProjectShellAllowed(rootDir, prefix, path5 = defaultConfigPath()) {
|
|
74
|
+
const trimmed = prefix.trim();
|
|
75
|
+
if (!trimmed) return false;
|
|
76
|
+
const cfg = readConfig(path5);
|
|
77
|
+
const existing = cfg.projects?.[rootDir]?.shellAllowed ?? [];
|
|
78
|
+
if (!existing.includes(trimmed)) return false;
|
|
79
|
+
const next = existing.filter((p) => p !== trimmed);
|
|
80
|
+
if (!cfg.projects) cfg.projects = {};
|
|
81
|
+
if (!cfg.projects[rootDir]) cfg.projects[rootDir] = {};
|
|
82
|
+
cfg.projects[rootDir].shellAllowed = next;
|
|
83
|
+
writeConfig(cfg, path5);
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
function clearProjectShellAllowed(rootDir, path5 = defaultConfigPath()) {
|
|
87
|
+
const cfg = readConfig(path5);
|
|
88
|
+
const existing = cfg.projects?.[rootDir]?.shellAllowed ?? [];
|
|
89
|
+
if (existing.length === 0) return 0;
|
|
90
|
+
if (!cfg.projects) cfg.projects = {};
|
|
91
|
+
if (!cfg.projects[rootDir]) cfg.projects[rootDir] = {};
|
|
92
|
+
cfg.projects[rootDir].shellAllowed = [];
|
|
93
|
+
writeConfig(cfg, path5);
|
|
94
|
+
return existing.length;
|
|
95
|
+
}
|
|
73
96
|
function loadEditMode(path5 = defaultConfigPath()) {
|
|
74
97
|
const v = readConfig(path5).editMode;
|
|
75
98
|
return v === "auto" ? "auto" : "review";
|
|
@@ -6760,6 +6783,159 @@ var SseTransport = class {
|
|
|
6760
6783
|
}
|
|
6761
6784
|
};
|
|
6762
6785
|
|
|
6786
|
+
// src/mcp/streamable-http.ts
|
|
6787
|
+
import { createParser as createParser3 } from "eventsource-parser";
|
|
6788
|
+
var SESSION_HEADER = "mcp-session-id";
|
|
6789
|
+
var StreamableHttpTransport = class {
|
|
6790
|
+
url;
|
|
6791
|
+
extraHeaders;
|
|
6792
|
+
queue = [];
|
|
6793
|
+
waiters = [];
|
|
6794
|
+
controller = new AbortController();
|
|
6795
|
+
/** Session id minted by server on (typically) the initialize response. */
|
|
6796
|
+
sessionId = null;
|
|
6797
|
+
closed = false;
|
|
6798
|
+
/** Background SSE read-loops kicked off by send(); awaited on close(). */
|
|
6799
|
+
streams = /* @__PURE__ */ new Set();
|
|
6800
|
+
constructor(opts) {
|
|
6801
|
+
this.url = opts.url;
|
|
6802
|
+
this.extraHeaders = opts.headers ?? {};
|
|
6803
|
+
}
|
|
6804
|
+
async send(message) {
|
|
6805
|
+
if (this.closed) throw new Error("MCP Streamable HTTP transport is closed");
|
|
6806
|
+
const headers = {
|
|
6807
|
+
"content-type": "application/json",
|
|
6808
|
+
// Both accepted — server picks. application/json first signals a
|
|
6809
|
+
// mild preference for the simpler shape when the response is a
|
|
6810
|
+
// single message.
|
|
6811
|
+
accept: "application/json, text/event-stream",
|
|
6812
|
+
...this.extraHeaders
|
|
6813
|
+
};
|
|
6814
|
+
if (this.sessionId !== null) headers["mcp-session-id"] = this.sessionId;
|
|
6815
|
+
let res;
|
|
6816
|
+
try {
|
|
6817
|
+
res = await fetch(this.url, {
|
|
6818
|
+
method: "POST",
|
|
6819
|
+
headers,
|
|
6820
|
+
body: JSON.stringify(message),
|
|
6821
|
+
signal: this.controller.signal
|
|
6822
|
+
});
|
|
6823
|
+
} catch (err) {
|
|
6824
|
+
throw new Error(`MCP Streamable HTTP POST ${this.url} failed: ${err.message}`);
|
|
6825
|
+
}
|
|
6826
|
+
const serverSessionId = res.headers.get(SESSION_HEADER);
|
|
6827
|
+
if (serverSessionId && this.sessionId === null) {
|
|
6828
|
+
this.sessionId = serverSessionId;
|
|
6829
|
+
}
|
|
6830
|
+
if (res.status === 404 && this.sessionId !== null) {
|
|
6831
|
+
await res.body?.cancel().catch(() => void 0);
|
|
6832
|
+
throw new Error(
|
|
6833
|
+
`MCP Streamable HTTP session expired (server returned 404 with Mcp-Session-Id "${this.sessionId}"). Reinitialize the client.`
|
|
6834
|
+
);
|
|
6835
|
+
}
|
|
6836
|
+
if (!res.ok) {
|
|
6837
|
+
const body = await res.text().catch(() => "");
|
|
6838
|
+
throw new Error(
|
|
6839
|
+
`MCP Streamable HTTP POST ${this.url} \u2192 ${res.status} ${res.statusText}${body ? `: ${body}` : ""}`
|
|
6840
|
+
);
|
|
6841
|
+
}
|
|
6842
|
+
if (res.status === 202) {
|
|
6843
|
+
await res.body?.cancel().catch(() => void 0);
|
|
6844
|
+
return;
|
|
6845
|
+
}
|
|
6846
|
+
const ct = (res.headers.get("content-type") ?? "").toLowerCase();
|
|
6847
|
+
if (ct.includes("application/json")) {
|
|
6848
|
+
let parsed;
|
|
6849
|
+
try {
|
|
6850
|
+
parsed = await res.json();
|
|
6851
|
+
} catch (err) {
|
|
6852
|
+
throw new Error(`MCP Streamable HTTP body wasn't valid JSON: ${err.message}`);
|
|
6853
|
+
}
|
|
6854
|
+
if (Array.isArray(parsed)) {
|
|
6855
|
+
for (const item of parsed) this.pushMessage(item);
|
|
6856
|
+
} else {
|
|
6857
|
+
this.pushMessage(parsed);
|
|
6858
|
+
}
|
|
6859
|
+
return;
|
|
6860
|
+
}
|
|
6861
|
+
if (ct.includes("text/event-stream")) {
|
|
6862
|
+
if (!res.body) {
|
|
6863
|
+
throw new Error("MCP Streamable HTTP SSE response had no body");
|
|
6864
|
+
}
|
|
6865
|
+
const stream = this.consumeStream(res.body);
|
|
6866
|
+
this.streams.add(stream);
|
|
6867
|
+
stream.finally(() => this.streams.delete(stream));
|
|
6868
|
+
return;
|
|
6869
|
+
}
|
|
6870
|
+
await res.body?.cancel().catch(() => void 0);
|
|
6871
|
+
}
|
|
6872
|
+
async *messages() {
|
|
6873
|
+
while (true) {
|
|
6874
|
+
if (this.queue.length > 0) {
|
|
6875
|
+
yield this.queue.shift();
|
|
6876
|
+
continue;
|
|
6877
|
+
}
|
|
6878
|
+
if (this.closed) return;
|
|
6879
|
+
const next = await new Promise((resolve12) => {
|
|
6880
|
+
this.waiters.push(resolve12);
|
|
6881
|
+
});
|
|
6882
|
+
if (next === null) return;
|
|
6883
|
+
yield next;
|
|
6884
|
+
}
|
|
6885
|
+
}
|
|
6886
|
+
async close() {
|
|
6887
|
+
if (this.closed) return;
|
|
6888
|
+
this.closed = true;
|
|
6889
|
+
while (this.waiters.length > 0) this.waiters.shift()(null);
|
|
6890
|
+
try {
|
|
6891
|
+
this.controller.abort();
|
|
6892
|
+
} catch {
|
|
6893
|
+
}
|
|
6894
|
+
await Promise.allSettled(Array.from(this.streams));
|
|
6895
|
+
}
|
|
6896
|
+
/** Visible for tests — confirm session header round-trip. */
|
|
6897
|
+
getSessionId() {
|
|
6898
|
+
return this.sessionId;
|
|
6899
|
+
}
|
|
6900
|
+
// ---------- internals ----------
|
|
6901
|
+
async consumeStream(body) {
|
|
6902
|
+
const parser = createParser3({
|
|
6903
|
+
onEvent: (ev) => {
|
|
6904
|
+
const type = ev.event ?? "message";
|
|
6905
|
+
if (type !== "message") return;
|
|
6906
|
+
try {
|
|
6907
|
+
const parsed = JSON.parse(ev.data);
|
|
6908
|
+
this.pushMessage(parsed);
|
|
6909
|
+
} catch {
|
|
6910
|
+
}
|
|
6911
|
+
}
|
|
6912
|
+
});
|
|
6913
|
+
const decoder = new TextDecoder();
|
|
6914
|
+
try {
|
|
6915
|
+
for await (const chunk of body) {
|
|
6916
|
+
if (this.closed) break;
|
|
6917
|
+
parser.feed(decoder.decode(chunk, { stream: true }));
|
|
6918
|
+
}
|
|
6919
|
+
} catch (err) {
|
|
6920
|
+
if (!this.closed) {
|
|
6921
|
+
this.pushMessage({
|
|
6922
|
+
jsonrpc: "2.0",
|
|
6923
|
+
id: null,
|
|
6924
|
+
error: {
|
|
6925
|
+
code: -32e3,
|
|
6926
|
+
message: `Streamable HTTP stream error: ${err.message}`
|
|
6927
|
+
}
|
|
6928
|
+
});
|
|
6929
|
+
}
|
|
6930
|
+
}
|
|
6931
|
+
}
|
|
6932
|
+
pushMessage(msg) {
|
|
6933
|
+
const waiter = this.waiters.shift();
|
|
6934
|
+
if (waiter) waiter(msg);
|
|
6935
|
+
else this.queue.push(msg);
|
|
6936
|
+
}
|
|
6937
|
+
};
|
|
6938
|
+
|
|
6763
6939
|
// src/mcp/shell-split.ts
|
|
6764
6940
|
function shellSplit(input) {
|
|
6765
6941
|
const tokens = [];
|
|
@@ -6812,6 +6988,7 @@ function shellSplit(input) {
|
|
|
6812
6988
|
// src/mcp/spec.ts
|
|
6813
6989
|
var NAME_PREFIX = /^([a-zA-Z_][a-zA-Z0-9_]*)=(.*)$/;
|
|
6814
6990
|
var HTTP_URL = /^https?:\/\//i;
|
|
6991
|
+
var STREAMABLE_PREFIX = /^streamable\+(https?:\/\/.+)$/i;
|
|
6815
6992
|
function parseMcpSpec(input) {
|
|
6816
6993
|
const trimmed = input.trim();
|
|
6817
6994
|
if (!trimmed) {
|
|
@@ -6823,6 +7000,10 @@ function parseMcpSpec(input) {
|
|
|
6823
7000
|
if (!body) {
|
|
6824
7001
|
throw new Error(`MCP spec has name but no command: ${input}`);
|
|
6825
7002
|
}
|
|
7003
|
+
const streamMatch = STREAMABLE_PREFIX.exec(body);
|
|
7004
|
+
if (streamMatch) {
|
|
7005
|
+
return { transport: "streamable-http", name, url: streamMatch[1] };
|
|
7006
|
+
}
|
|
6826
7007
|
if (HTTP_URL.test(body)) {
|
|
6827
7008
|
return { transport: "sse", name, url: body };
|
|
6828
7009
|
}
|
|
@@ -11579,6 +11760,12 @@ var SLASH_COMMANDS = [
|
|
|
11579
11760
|
argsHint: "[reload]",
|
|
11580
11761
|
summary: "list active hooks (settings.json under .reasonix/) \xB7 reload re-reads from disk"
|
|
11581
11762
|
},
|
|
11763
|
+
{
|
|
11764
|
+
cmd: "permissions",
|
|
11765
|
+
argsHint: "[list|add <prefix>|remove <prefix|N>|clear confirm]",
|
|
11766
|
+
summary: "show / edit shell allowlist (builtin read-only \xB7 per-project: ~/.reasonix/config.json)",
|
|
11767
|
+
argCompleter: ["list", "add", "remove", "clear"]
|
|
11768
|
+
},
|
|
11582
11769
|
{
|
|
11583
11770
|
cmd: "cwd",
|
|
11584
11771
|
argsHint: "<path>",
|
|
@@ -13130,6 +13317,150 @@ var handlers9 = {
|
|
|
13130
13317
|
compact
|
|
13131
13318
|
};
|
|
13132
13319
|
|
|
13320
|
+
// src/cli/ui/slash/handlers/permissions.ts
|
|
13321
|
+
var permissions = (args, _loop, ctx) => {
|
|
13322
|
+
const sub = (args[0] ?? "").toLowerCase();
|
|
13323
|
+
const root = ctx.codeRoot;
|
|
13324
|
+
const mode2 = ctx.editMode ?? null;
|
|
13325
|
+
if (sub === "" || sub === "list" || sub === "ls") {
|
|
13326
|
+
return { info: renderListing(root, mode2) };
|
|
13327
|
+
}
|
|
13328
|
+
if (!root) {
|
|
13329
|
+
return {
|
|
13330
|
+
info: "/permissions add / remove / clear are only available inside `reasonix code` \u2014 they edit the project-scoped allowlist (`~/.reasonix/config.json` projects[<root>].shellAllowed)."
|
|
13331
|
+
};
|
|
13332
|
+
}
|
|
13333
|
+
if (sub === "add") {
|
|
13334
|
+
const prefix = args.slice(1).join(" ").trim();
|
|
13335
|
+
if (!prefix) {
|
|
13336
|
+
return {
|
|
13337
|
+
info: 'usage: /permissions add <prefix> (multi-token OK: /permissions add "git push origin")'
|
|
13338
|
+
};
|
|
13339
|
+
}
|
|
13340
|
+
const before = loadProjectShellAllowed(root);
|
|
13341
|
+
if (before.includes(prefix)) {
|
|
13342
|
+
return { info: `\u25B8 already allowed: ${prefix}` };
|
|
13343
|
+
}
|
|
13344
|
+
if (BUILTIN_ALLOWLIST.includes(prefix)) {
|
|
13345
|
+
return {
|
|
13346
|
+
info: `\u25B8 \`${prefix}\` is already in the builtin allowlist \u2014 no per-project entry needed. (Builtin entries are always on.)`
|
|
13347
|
+
};
|
|
13348
|
+
}
|
|
13349
|
+
addProjectShellAllowed(root, prefix);
|
|
13350
|
+
return {
|
|
13351
|
+
info: `\u25B8 added: ${prefix}
|
|
13352
|
+
\u2192 next \`${prefix}\` invocation runs without prompting in this project.`
|
|
13353
|
+
};
|
|
13354
|
+
}
|
|
13355
|
+
if (sub === "remove" || sub === "rm" || sub === "delete") {
|
|
13356
|
+
const target = args.slice(1).join(" ").trim();
|
|
13357
|
+
if (!target) {
|
|
13358
|
+
return {
|
|
13359
|
+
info: "usage: /permissions remove <prefix-or-index> (e.g. /permissions remove 3, or /permissions remove npm)"
|
|
13360
|
+
};
|
|
13361
|
+
}
|
|
13362
|
+
const existing = loadProjectShellAllowed(root);
|
|
13363
|
+
let prefix = null;
|
|
13364
|
+
if (/^\d+$/.test(target)) {
|
|
13365
|
+
const idx = Number.parseInt(target, 10);
|
|
13366
|
+
if (idx < 1 || idx > existing.length) {
|
|
13367
|
+
return {
|
|
13368
|
+
info: existing.length === 0 ? "\u25B8 no project allowlist entries to remove." : `\u25B8 index out of range: ${idx} (project list has ${existing.length} entries)`
|
|
13369
|
+
};
|
|
13370
|
+
}
|
|
13371
|
+
prefix = existing[idx - 1] ?? null;
|
|
13372
|
+
} else {
|
|
13373
|
+
prefix = target;
|
|
13374
|
+
}
|
|
13375
|
+
if (prefix === null) return { info: "\u25B8 nothing to remove." };
|
|
13376
|
+
if (BUILTIN_ALLOWLIST.includes(prefix) && !existing.includes(prefix)) {
|
|
13377
|
+
return {
|
|
13378
|
+
info: `\u25B8 \`${prefix}\` is in the builtin allowlist (read-only). Builtin entries can't be removed at runtime \u2014 they're baked into the binary.`
|
|
13379
|
+
};
|
|
13380
|
+
}
|
|
13381
|
+
const ok = removeProjectShellAllowed(root, prefix);
|
|
13382
|
+
return {
|
|
13383
|
+
info: ok ? `\u25B8 removed: ${prefix}` : `\u25B8 no such project entry: ${prefix} (try /permissions list to see what's stored)`
|
|
13384
|
+
};
|
|
13385
|
+
}
|
|
13386
|
+
if (sub === "clear") {
|
|
13387
|
+
if ((args[1] ?? "").toLowerCase() !== "confirm") {
|
|
13388
|
+
const count = loadProjectShellAllowed(root).length;
|
|
13389
|
+
return {
|
|
13390
|
+
info: count === 0 ? "\u25B8 project allowlist is already empty." : `about to drop ${count} project allowlist entr${count === 1 ? "y" : "ies"} for ${root}. Re-run with the word 'confirm' to proceed: /permissions clear confirm`
|
|
13391
|
+
};
|
|
13392
|
+
}
|
|
13393
|
+
const dropped = clearProjectShellAllowed(root);
|
|
13394
|
+
return {
|
|
13395
|
+
info: dropped === 0 ? "\u25B8 project allowlist was already empty \u2014 nothing changed." : `\u25B8 cleared ${dropped} project allowlist entr${dropped === 1 ? "y" : "ies"}.`
|
|
13396
|
+
};
|
|
13397
|
+
}
|
|
13398
|
+
return {
|
|
13399
|
+
info: [
|
|
13400
|
+
"usage: /permissions [list] show current state",
|
|
13401
|
+
' /permissions add <prefix> persist (e.g. "npm run build")',
|
|
13402
|
+
" /permissions remove <prefix-or-N> drop one entry",
|
|
13403
|
+
" /permissions clear confirm wipe every project entry"
|
|
13404
|
+
].join("\n")
|
|
13405
|
+
};
|
|
13406
|
+
};
|
|
13407
|
+
function renderListing(root, mode2) {
|
|
13408
|
+
const lines = [];
|
|
13409
|
+
if (mode2 === "yolo") {
|
|
13410
|
+
lines.push(
|
|
13411
|
+
"\u25B8 edit mode: YOLO \u2014 every shell command auto-runs, allowlist is bypassed. /mode review to re-enable prompts."
|
|
13412
|
+
);
|
|
13413
|
+
} else if (mode2 === "auto") {
|
|
13414
|
+
lines.push(
|
|
13415
|
+
"\u25B8 edit mode: auto \u2014 edits auto-apply, shell still gated by allowlist (or ShellConfirm prompt for non-allowlisted)."
|
|
13416
|
+
);
|
|
13417
|
+
} else if (mode2 === "review") {
|
|
13418
|
+
lines.push(
|
|
13419
|
+
"\u25B8 edit mode: review \u2014 both edits and non-allowlisted shell commands ask before running."
|
|
13420
|
+
);
|
|
13421
|
+
}
|
|
13422
|
+
lines.push("");
|
|
13423
|
+
if (root) {
|
|
13424
|
+
const project = loadProjectShellAllowed(root);
|
|
13425
|
+
lines.push(`Project allowlist (${project.length}) \u2014 ${root}`);
|
|
13426
|
+
if (project.length === 0) {
|
|
13427
|
+
lines.push(' (none \u2014 pick "always allow" on a ShellConfirm prompt to add one,');
|
|
13428
|
+
lines.push(" or `/permissions add <prefix>` directly.)");
|
|
13429
|
+
} else {
|
|
13430
|
+
project.forEach((p, i) => {
|
|
13431
|
+
lines.push(` ${String(i + 1).padStart(2)}. ${p}`);
|
|
13432
|
+
});
|
|
13433
|
+
}
|
|
13434
|
+
} else {
|
|
13435
|
+
lines.push("Project allowlist \u2014 (no project root; chat mode shows builtin entries only)");
|
|
13436
|
+
}
|
|
13437
|
+
lines.push("");
|
|
13438
|
+
lines.push(`Builtin allowlist (${BUILTIN_ALLOWLIST.length}) \u2014 read-only, baked in`);
|
|
13439
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
13440
|
+
for (const entry of BUILTIN_ALLOWLIST) {
|
|
13441
|
+
const head = entry.split(" ")[0] ?? entry;
|
|
13442
|
+
if (!grouped.has(head)) grouped.set(head, []);
|
|
13443
|
+
grouped.get(head).push(entry);
|
|
13444
|
+
}
|
|
13445
|
+
for (const [head, items] of grouped) {
|
|
13446
|
+
if (items.length === 1 && items[0] === head) {
|
|
13447
|
+
lines.push(` \xB7 ${head}`);
|
|
13448
|
+
} else {
|
|
13449
|
+
const tail = items.map((i) => i.slice(head.length).trim() || "(bare)").join(", ");
|
|
13450
|
+
lines.push(` \xB7 ${head}: ${tail}`);
|
|
13451
|
+
}
|
|
13452
|
+
}
|
|
13453
|
+
lines.push("");
|
|
13454
|
+
lines.push(
|
|
13455
|
+
"Subcommands: /permissions add <prefix> \xB7 /permissions remove <prefix-or-N> \xB7 /permissions clear confirm"
|
|
13456
|
+
);
|
|
13457
|
+
return lines.join("\n");
|
|
13458
|
+
}
|
|
13459
|
+
var handlers10 = {
|
|
13460
|
+
permissions,
|
|
13461
|
+
perms: permissions
|
|
13462
|
+
};
|
|
13463
|
+
|
|
13133
13464
|
// src/cli/ui/slash/handlers/plans.ts
|
|
13134
13465
|
import { basename } from "path";
|
|
13135
13466
|
var plans = (_args, loop2) => {
|
|
@@ -13209,7 +13540,7 @@ var replay = (args, loop2) => {
|
|
|
13209
13540
|
}
|
|
13210
13541
|
};
|
|
13211
13542
|
};
|
|
13212
|
-
var
|
|
13543
|
+
var handlers11 = {
|
|
13213
13544
|
plans,
|
|
13214
13545
|
replay
|
|
13215
13546
|
};
|
|
@@ -13582,7 +13913,7 @@ async function readIndexMeta(rootDir) {
|
|
|
13582
13913
|
return null;
|
|
13583
13914
|
}
|
|
13584
13915
|
}
|
|
13585
|
-
var
|
|
13916
|
+
var handlers12 = {
|
|
13586
13917
|
semantic
|
|
13587
13918
|
};
|
|
13588
13919
|
|
|
@@ -13617,7 +13948,7 @@ var forget = (_args, loop2) => {
|
|
|
13617
13948
|
info: ok ? `\u25B8 deleted session "${name}" \u2014 current screen still shows the conversation, but next launch starts fresh` : `could not delete session "${name}" (already gone?)`
|
|
13618
13949
|
};
|
|
13619
13950
|
};
|
|
13620
|
-
var
|
|
13951
|
+
var handlers13 = {
|
|
13621
13952
|
sessions,
|
|
13622
13953
|
forget
|
|
13623
13954
|
};
|
|
@@ -13693,7 +14024,7 @@ ${found.body}${argsLine}`;
|
|
|
13693
14024
|
resubmit: payload
|
|
13694
14025
|
};
|
|
13695
14026
|
};
|
|
13696
|
-
var
|
|
14027
|
+
var handlers14 = {
|
|
13697
14028
|
skill,
|
|
13698
14029
|
skills: skill
|
|
13699
14030
|
};
|
|
@@ -13712,7 +14043,8 @@ var HANDLERS = {
|
|
|
13712
14043
|
...handlers10,
|
|
13713
14044
|
...handlers11,
|
|
13714
14045
|
...handlers12,
|
|
13715
|
-
...handlers13
|
|
14046
|
+
...handlers13,
|
|
14047
|
+
...handlers14
|
|
13716
14048
|
};
|
|
13717
14049
|
function handleSlash(cmd, args, loop2, ctx = {}) {
|
|
13718
14050
|
const h = HANDLERS[cmd];
|
|
@@ -16513,7 +16845,7 @@ async function chatCommand(opts) {
|
|
|
16513
16845
|
try {
|
|
16514
16846
|
const spec = parseMcpSpec(raw);
|
|
16515
16847
|
const prefix = spec.name ? `${spec.name}_` : requestedSpecs.length === 1 && opts.mcpPrefix ? opts.mcpPrefix : "";
|
|
16516
|
-
const transport = spec.transport === "sse" ? new SseTransport({ url: spec.url }) : new StdioTransport({ command: spec.command, args: spec.args });
|
|
16848
|
+
const transport = spec.transport === "sse" ? new SseTransport({ url: spec.url }) : spec.transport === "streamable-http" ? new StreamableHttpTransport({ url: spec.url }) : new StdioTransport({ command: spec.command, args: spec.args });
|
|
16517
16849
|
const mcp3 = new McpClient({ transport });
|
|
16518
16850
|
await mcp3.initialize();
|
|
16519
16851
|
const bridge = await bridgeMcpTools(mcp3, {
|
|
@@ -16535,7 +16867,7 @@ async function chatCommand(opts) {
|
|
|
16535
16867
|
};
|
|
16536
16868
|
}
|
|
16537
16869
|
const label = spec.name ?? "anon";
|
|
16538
|
-
const source = spec.transport === "sse" ? spec.url : `${spec.command} ${spec.args.join(" ")}`;
|
|
16870
|
+
const source = spec.transport === "sse" || spec.transport === "streamable-http" ? spec.url : `${spec.command} ${spec.args.join(" ")}`;
|
|
16539
16871
|
process.stderr.write(
|
|
16540
16872
|
`\u25B8 MCP[${label}]: ${bridge.registeredNames.length} tool(s) from ${source}
|
|
16541
16873
|
`
|
|
@@ -17664,7 +17996,7 @@ function makeTtyWriter() {
|
|
|
17664
17996
|
// src/cli/commands/mcp-inspect.ts
|
|
17665
17997
|
async function mcpInspectCommand(opts) {
|
|
17666
17998
|
const spec = parseMcpSpec(opts.spec);
|
|
17667
|
-
const transport = spec.transport === "sse" ? new SseTransport({ url: spec.url }) : new StdioTransport({ command: spec.command, args: spec.args });
|
|
17999
|
+
const transport = spec.transport === "sse" ? new SseTransport({ url: spec.url }) : spec.transport === "streamable-http" ? new StreamableHttpTransport({ url: spec.url }) : new StdioTransport({ command: spec.command, args: spec.args });
|
|
17668
18000
|
const client = new McpClient({ transport });
|
|
17669
18001
|
try {
|
|
17670
18002
|
await client.initialize();
|
|
@@ -17996,11 +18328,11 @@ async function runCommand2(opts) {
|
|
|
17996
18328
|
try {
|
|
17997
18329
|
const spec = parseMcpSpec(raw);
|
|
17998
18330
|
const prefix2 = spec.name ? `${spec.name}_` : requestedSpecs.length === 1 && opts.mcpPrefix ? opts.mcpPrefix : "";
|
|
17999
|
-
const transport = spec.transport === "sse" ? new SseTransport({ url: spec.url }) : new StdioTransport({ command: spec.command, args: spec.args });
|
|
18331
|
+
const transport = spec.transport === "sse" ? new SseTransport({ url: spec.url }) : spec.transport === "streamable-http" ? new StreamableHttpTransport({ url: spec.url }) : new StdioTransport({ command: spec.command, args: spec.args });
|
|
18000
18332
|
const mcp3 = new McpClient({ transport });
|
|
18001
18333
|
await mcp3.initialize();
|
|
18002
18334
|
const bridge = await bridgeMcpTools(mcp3, { registry: tools, namePrefix: prefix2 });
|
|
18003
|
-
const source = spec.transport === "sse" ? spec.url : `${spec.command} ${spec.args.join(" ")}`;
|
|
18335
|
+
const source = spec.transport === "sse" || spec.transport === "streamable-http" ? spec.url : `${spec.command} ${spec.args.join(" ")}`;
|
|
18004
18336
|
process.stderr.write(
|
|
18005
18337
|
`\u25B8 MCP[${spec.name ?? "anon"}]: ${bridge.registeredNames.length} tool(s) from ${source}
|
|
18006
18338
|
`
|