cascade-ai 0.12.17 → 0.12.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/dist/cli.cjs CHANGED
@@ -4,6 +4,10 @@ var Anthropic = require('@anthropic-ai/sdk');
4
4
  var OpenAI = require('openai');
5
5
  var genai = require('@google/genai');
6
6
  var dns = require('dns');
7
+ var http = require('http');
8
+ var https = require('https');
9
+ var zlib = require('zlib');
10
+ var stream = require('stream');
7
11
  var ink = require('ink');
8
12
  var commander = require('commander');
9
13
  var React2 = require('react');
@@ -33,7 +37,6 @@ var worker_threads = require('worker_threads');
33
37
  var Spinner = require('ink-spinner');
34
38
  var ora = require('ora');
35
39
  var SelectInput = require('ink-select-input');
36
- var http = require('http');
37
40
  var express = require('express');
38
41
  var rateLimit = require('express-rate-limit');
39
42
  var bcrypt = require('bcryptjs');
@@ -65,6 +68,9 @@ function _interopNamespace(e) {
65
68
  var Anthropic__default = /*#__PURE__*/_interopDefault(Anthropic);
66
69
  var OpenAI__default = /*#__PURE__*/_interopDefault(OpenAI);
67
70
  var dns__default = /*#__PURE__*/_interopDefault(dns);
71
+ var http__default = /*#__PURE__*/_interopDefault(http);
72
+ var https__default = /*#__PURE__*/_interopDefault(https);
73
+ var zlib__default = /*#__PURE__*/_interopDefault(zlib);
68
74
  var React2__default = /*#__PURE__*/_interopDefault(React2);
69
75
  var chalk9__default = /*#__PURE__*/_interopDefault(chalk9);
70
76
  var dotenv__default = /*#__PURE__*/_interopDefault(dotenv);
@@ -103,7 +109,7 @@ var __export = (target, all) => {
103
109
  var CASCADE_VERSION, CASCADE_CONFIG_FILE, CASCADE_DB_FILE, CASCADE_DASHBOARD_SECRET_FILE, GLOBAL_CONFIG_DIR, GLOBAL_DB_FILE, GLOBAL_KEYSTORE_FILE, GLOBAL_RUNTIME_DB_FILE, DEFAULT_DASHBOARD_PORT, DEFAULT_CONTEXT_LIMIT, DEFAULT_AUTO_SUMMARIZE_AT, MODELS, T1_MODEL_PRIORITY, T2_MODEL_PRIORITY, T3_MODEL_PRIORITY, VISION_MODEL_PRIORITY, COMPLEXITY_T2_COUNT, THEME_NAMES, DEFAULT_THEME, OLLAMA_BASE_URL, LM_STUDIO_BASE_URL, AZURE_BASE_URL_TEMPLATE, TOOL_NAMES, DEFAULT_APPROVAL_REQUIRED;
104
110
  var init_constants = __esm({
105
111
  "src/constants.ts"() {
106
- CASCADE_VERSION = "0.12.17";
112
+ CASCADE_VERSION = "0.12.19";
107
113
  CASCADE_CONFIG_FILE = ".cascade/config.json";
108
114
  CASCADE_DB_FILE = ".cascade/memory.db";
109
115
  CASCADE_DASHBOARD_SECRET_FILE = ".cascade/dashboard-secret";
@@ -1213,12 +1219,75 @@ function preferIpv4Host(url) {
1213
1219
  if (!url) return url;
1214
1220
  return url.replace(/^(https?:\/\/)localhost(?=[:/]|$)/i, "$1127.0.0.1");
1215
1221
  }
1222
+ async function nodeHttpFetch(input, init = {}, redirectCount = 0) {
1223
+ const urlStr = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
1224
+ const u = new URL(preferIpv4Host(urlStr) ?? urlStr);
1225
+ const lib = u.protocol === "https:" ? https__default.default : http__default.default;
1226
+ const method = (init.method ?? "GET").toUpperCase();
1227
+ const headers = {};
1228
+ const h = init.headers;
1229
+ if (h instanceof Headers) h.forEach((v, k) => {
1230
+ headers[k] = v;
1231
+ });
1232
+ else if (Array.isArray(h)) for (const [k, v] of h) headers[k] = v;
1233
+ else if (h) Object.assign(headers, h);
1234
+ if (!Object.keys(headers).some((k) => k.toLowerCase() === "accept-encoding")) {
1235
+ headers["accept-encoding"] = "gzip, deflate, br";
1236
+ }
1237
+ const body = init.body == null ? void 0 : typeof init.body === "string" ? init.body : Buffer.from(init.body);
1238
+ return new Promise((resolve, reject) => {
1239
+ const req = lib.request(
1240
+ {
1241
+ hostname: u.hostname,
1242
+ port: u.port || (u.protocol === "https:" ? 443 : 80),
1243
+ path: u.pathname + u.search,
1244
+ method,
1245
+ headers
1246
+ },
1247
+ (res) => {
1248
+ const status = res.statusCode ?? 200;
1249
+ const location = res.headers.location;
1250
+ if (status >= 300 && status < 400 && location && redirectCount < MAX_REDIRECTS) {
1251
+ res.resume();
1252
+ const nextUrl = new URL(location, u).href;
1253
+ const downgrade = status === 303 || (status === 301 || status === 302) && method !== "GET" && method !== "HEAD";
1254
+ const nextInit = downgrade ? { ...init, method: "GET", body: void 0 } : init;
1255
+ resolve(nodeHttpFetch(nextUrl, nextInit, redirectCount + 1));
1256
+ return;
1257
+ }
1258
+ const encoding = (res.headers["content-encoding"] ?? "").toLowerCase();
1259
+ let bodyStream = res;
1260
+ if (encoding === "gzip" || encoding === "x-gzip") bodyStream = res.pipe(zlib__default.default.createGunzip());
1261
+ else if (encoding === "deflate") bodyStream = res.pipe(zlib__default.default.createInflate());
1262
+ else if (encoding === "br") bodyStream = res.pipe(zlib__default.default.createBrotliDecompress());
1263
+ const stream$1 = stream.Readable.toWeb(bodyStream);
1264
+ const respHeaders = new Headers();
1265
+ for (const [k, v] of Object.entries(res.headers)) {
1266
+ if (k === "content-encoding" || k === "content-length") continue;
1267
+ if (Array.isArray(v)) respHeaders.set(k, v.join(", "));
1268
+ else if (typeof v === "string") respHeaders.set(k, v);
1269
+ }
1270
+ resolve(new Response(stream$1, {
1271
+ status,
1272
+ statusText: res.statusMessage ?? "",
1273
+ headers: respHeaders
1274
+ }));
1275
+ }
1276
+ );
1277
+ req.on("error", reject);
1278
+ req.setTimeout(15e3, () => req.destroy(new Error("request timed out")));
1279
+ if (body !== void 0) req.write(body);
1280
+ req.end();
1281
+ });
1282
+ }
1283
+ var MAX_REDIRECTS;
1216
1284
  var init_net = __esm({
1217
1285
  "src/utils/net.ts"() {
1218
1286
  try {
1219
1287
  dns__default.default.setDefaultResultOrder("ipv4first");
1220
1288
  } catch {
1221
1289
  }
1290
+ MAX_REDIRECTS = 5;
1222
1291
  }
1223
1292
  });
1224
1293
 
@@ -1456,7 +1525,8 @@ var init_openai_compatible = __esm({
1456
1525
  super(config, model);
1457
1526
  this.client = new OpenAI__default.default({
1458
1527
  apiKey: config.apiKey ?? "not-required",
1459
- baseURL: preferIpv4Host(config.baseUrl)
1528
+ baseURL: preferIpv4Host(config.baseUrl),
1529
+ fetch: nodeHttpFetch
1460
1530
  });
1461
1531
  }
1462
1532
  modelsUrl() {
@@ -1468,14 +1538,8 @@ var init_openai_compatible = __esm({
1468
1538
  if (this.config.apiKey) h["Authorization"] = `Bearer ${this.config.apiKey}`;
1469
1539
  return h;
1470
1540
  }
1471
- // Discover models with a tolerant direct GET instead of the OpenAI SDK's typed
1472
- // `models.list()`. Local servers (llama.cpp / LM Studio / vLLM) return
1473
- // non-standard `/v1/models` payloads — an extra `models` array, filesystem
1474
- // path ids (`C:\…\model.gguf`) — that can make the SDK's typed pagination
1475
- // throw, which previously surfaced as a misleading "endpoint unreachable".
1476
- // A plain fetch + lenient parse is robust and reports the real HTTP error.
1477
1541
  async listModels() {
1478
- const res = await fetch(this.modelsUrl(), { headers: this.authHeaders() });
1542
+ const res = await nodeHttpFetch(this.modelsUrl(), { headers: this.authHeaders() });
1479
1543
  if (!res.ok) throw new Error(`models endpoint ${this.modelsUrl()} returned HTTP ${res.status}`);
1480
1544
  const body = await res.json();
1481
1545
  const raw = Array.isArray(body?.data) ? body.data : Array.isArray(body?.models) ? body.models : [];
@@ -1503,7 +1567,7 @@ var init_openai_compatible = __esm({
1503
1567
  }
1504
1568
  async isAvailable() {
1505
1569
  try {
1506
- const res = await fetch(this.modelsUrl(), { headers: this.authHeaders() });
1570
+ const res = await nodeHttpFetch(this.modelsUrl(), { headers: this.authHeaders() });
1507
1571
  return res.ok;
1508
1572
  } catch {
1509
1573
  return false;
@@ -8927,7 +8991,7 @@ var SsrfBlockedError = class extends Error {
8927
8991
  }
8928
8992
  };
8929
8993
  var ALLOWED_PROTOCOLS = /* @__PURE__ */ new Set(["http:", "https:"]);
8930
- var MAX_REDIRECTS = 5;
8994
+ var MAX_REDIRECTS2 = 5;
8931
8995
  function allowLocal() {
8932
8996
  return process.env["CASCADE_ALLOW_LOCAL_FETCH"] === "1";
8933
8997
  }
@@ -8995,7 +9059,7 @@ async function assertPublicUrl(rawUrl) {
8995
9059
  }
8996
9060
  async function safeFetch(rawUrl, init = {}) {
8997
9061
  let currentUrl = (await assertPublicUrl(rawUrl)).toString();
8998
- for (let i = 0; i <= MAX_REDIRECTS; i++) {
9062
+ for (let i = 0; i <= MAX_REDIRECTS2; i++) {
8999
9063
  const resp = await fetch(currentUrl, { ...init, redirect: "manual" });
9000
9064
  if (resp.status < 300 || resp.status >= 400) return resp;
9001
9065
  const location = resp.headers.get("location");
@@ -9004,7 +9068,7 @@ async function safeFetch(rawUrl, init = {}) {
9004
9068
  await assertPublicUrl(next.toString());
9005
9069
  currentUrl = next.toString();
9006
9070
  }
9007
- throw new SsrfBlockedError(`Too many redirects (>${MAX_REDIRECTS}).`);
9071
+ throw new SsrfBlockedError(`Too many redirects (>${MAX_REDIRECTS2}).`);
9008
9072
  }
9009
9073
 
9010
9074
  // src/tools/web-fetch.ts