cascade-ai 0.76.0 → 0.77.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/README.md +2 -2
- package/dist/cli.cjs +948 -515
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +931 -498
- package/dist/cli.js.map +1 -1
- package/dist/desktop-core.cjs +24340 -3171
- package/dist/index.cjs +899 -475
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1139 -16
- package/dist/index.d.ts +1139 -16
- package/dist/index.js +882 -459
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/web/dist/assets/index-DoU1RNKq.js +246 -0
- package/web/dist/assets/react-DmRRAgLv.js +1 -0
- package/web/dist/assets/{reactflow-Clz8xC7C.js → reactflow-CkXCC9kc.js} +2 -2
- package/web/dist/assets/{socketio-BcxXcwBL.js → socketio-SYmKJpIj.js} +1 -1
- package/web/dist/index.html +3 -3
- package/web/dist/assets/index-DFRrUnoJ.js +0 -246
- package/web/dist/assets/react-BP1N17hq.js +0 -1
package/dist/cli.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var dnsCallback = require('dns');
|
|
4
4
|
var http = require('http');
|
|
5
5
|
var https = require('https');
|
|
6
6
|
var zlib = require('zlib');
|
|
@@ -9,8 +9,8 @@ var Anthropic = require('@anthropic-ai/sdk');
|
|
|
9
9
|
var OpenAI = require('openai');
|
|
10
10
|
var genai = require('@google/genai');
|
|
11
11
|
var Database2 = require('better-sqlite3');
|
|
12
|
-
var
|
|
13
|
-
var
|
|
12
|
+
var path36 = require('path');
|
|
13
|
+
var fs33 = require('fs');
|
|
14
14
|
var os10 = require('os');
|
|
15
15
|
var crypto = require('crypto');
|
|
16
16
|
var ink = require('ink');
|
|
@@ -31,6 +31,7 @@ var simpleGit = require('simple-git');
|
|
|
31
31
|
var PDFDocument = require('pdfkit');
|
|
32
32
|
var dns2 = require('dns/promises');
|
|
33
33
|
var net = require('net');
|
|
34
|
+
var undici = require('undici');
|
|
34
35
|
var index_js = require('@modelcontextprotocol/sdk/client/index.js');
|
|
35
36
|
var stdio_js = require('@modelcontextprotocol/sdk/client/stdio.js');
|
|
36
37
|
var streamableHttp_js = require('@modelcontextprotocol/sdk/client/streamableHttp.js');
|
|
@@ -70,15 +71,15 @@ function _interopNamespace(e) {
|
|
|
70
71
|
return Object.freeze(n);
|
|
71
72
|
}
|
|
72
73
|
|
|
73
|
-
var
|
|
74
|
+
var dnsCallback__default = /*#__PURE__*/_interopDefault(dnsCallback);
|
|
74
75
|
var http__default = /*#__PURE__*/_interopDefault(http);
|
|
75
76
|
var https__default = /*#__PURE__*/_interopDefault(https);
|
|
76
77
|
var zlib__default = /*#__PURE__*/_interopDefault(zlib);
|
|
77
78
|
var Anthropic__default = /*#__PURE__*/_interopDefault(Anthropic);
|
|
78
79
|
var OpenAI__default = /*#__PURE__*/_interopDefault(OpenAI);
|
|
79
80
|
var Database2__default = /*#__PURE__*/_interopDefault(Database2);
|
|
80
|
-
var
|
|
81
|
-
var
|
|
81
|
+
var path36__default = /*#__PURE__*/_interopDefault(path36);
|
|
82
|
+
var fs33__default = /*#__PURE__*/_interopDefault(fs33);
|
|
82
83
|
var os10__default = /*#__PURE__*/_interopDefault(os10);
|
|
83
84
|
var crypto__default = /*#__PURE__*/_interopDefault(crypto);
|
|
84
85
|
var React2__default = /*#__PURE__*/_interopDefault(React2);
|
|
@@ -1848,7 +1849,7 @@ var CASCADE_VERSION, CASCADE_CONFIG_FILE, CASCADE_DB_FILE, CASCADE_DASHBOARD_SEC
|
|
|
1848
1849
|
var init_constants = __esm({
|
|
1849
1850
|
"src/constants.ts"() {
|
|
1850
1851
|
init_pricing();
|
|
1851
|
-
CASCADE_VERSION = "0.
|
|
1852
|
+
CASCADE_VERSION = "0.77.0";
|
|
1852
1853
|
CASCADE_CONFIG_FILE = ".cascade/config.json";
|
|
1853
1854
|
CASCADE_DB_FILE = ".cascade/memory.db";
|
|
1854
1855
|
CASCADE_DASHBOARD_SECRET_FILE = ".cascade/dashboard-secret";
|
|
@@ -1861,64 +1862,88 @@ var init_constants = __esm({
|
|
|
1861
1862
|
DEFAULT_CONTEXT_LIMIT = 2e5;
|
|
1862
1863
|
DEFAULT_AUTO_SUMMARIZE_AT = 15e4;
|
|
1863
1864
|
MODELS = {
|
|
1864
|
-
// Anthropic
|
|
1865
|
-
"claude-
|
|
1866
|
-
id: "claude-
|
|
1867
|
-
name: "Claude
|
|
1865
|
+
// Anthropic — active Claude API models (2026-08-27).
|
|
1866
|
+
"claude-fable-5": {
|
|
1867
|
+
id: "claude-fable-5",
|
|
1868
|
+
name: "Claude Fable 5",
|
|
1868
1869
|
provider: "anthropic",
|
|
1869
|
-
contextWindow:
|
|
1870
|
+
contextWindow: 1e6,
|
|
1870
1871
|
isVisionCapable: true,
|
|
1871
|
-
inputCostPer1kTokens: 0.
|
|
1872
|
-
outputCostPer1kTokens: 0.
|
|
1873
|
-
maxOutputTokens:
|
|
1872
|
+
inputCostPer1kTokens: 0.01,
|
|
1873
|
+
outputCostPer1kTokens: 0.05,
|
|
1874
|
+
maxOutputTokens: 128e3,
|
|
1874
1875
|
supportsStreaming: true,
|
|
1875
1876
|
isLocal: false
|
|
1876
1877
|
},
|
|
1877
|
-
"claude-
|
|
1878
|
-
id: "claude-
|
|
1879
|
-
name: "Claude
|
|
1878
|
+
"claude-opus-5": {
|
|
1879
|
+
id: "claude-opus-5",
|
|
1880
|
+
name: "Claude Opus 5",
|
|
1880
1881
|
provider: "anthropic",
|
|
1881
|
-
contextWindow:
|
|
1882
|
+
contextWindow: 1e6,
|
|
1882
1883
|
isVisionCapable: true,
|
|
1883
|
-
inputCostPer1kTokens:
|
|
1884
|
-
outputCostPer1kTokens: 0.
|
|
1885
|
-
maxOutputTokens:
|
|
1884
|
+
inputCostPer1kTokens: 5e-3,
|
|
1885
|
+
outputCostPer1kTokens: 0.025,
|
|
1886
|
+
maxOutputTokens: 128e3,
|
|
1886
1887
|
supportsStreaming: true,
|
|
1887
1888
|
isLocal: false
|
|
1888
1889
|
},
|
|
1889
|
-
"claude-
|
|
1890
|
-
id: "claude-
|
|
1891
|
-
name: "Claude
|
|
1890
|
+
"claude-opus-4-8": {
|
|
1891
|
+
id: "claude-opus-4-8",
|
|
1892
|
+
name: "Claude Opus 4.8",
|
|
1892
1893
|
provider: "anthropic",
|
|
1893
|
-
contextWindow:
|
|
1894
|
+
contextWindow: 1e6,
|
|
1894
1895
|
isVisionCapable: true,
|
|
1895
|
-
inputCostPer1kTokens:
|
|
1896
|
-
outputCostPer1kTokens:
|
|
1897
|
-
maxOutputTokens:
|
|
1896
|
+
inputCostPer1kTokens: 5e-3,
|
|
1897
|
+
outputCostPer1kTokens: 0.025,
|
|
1898
|
+
maxOutputTokens: 128e3,
|
|
1898
1899
|
supportsStreaming: true,
|
|
1899
1900
|
isLocal: false
|
|
1900
1901
|
},
|
|
1901
|
-
"claude-
|
|
1902
|
-
id: "claude-
|
|
1903
|
-
name: "Claude
|
|
1902
|
+
"claude-opus-4-7": {
|
|
1903
|
+
id: "claude-opus-4-7",
|
|
1904
|
+
name: "Claude Opus 4.7",
|
|
1904
1905
|
provider: "anthropic",
|
|
1905
|
-
contextWindow:
|
|
1906
|
+
contextWindow: 1e6,
|
|
1906
1907
|
isVisionCapable: true,
|
|
1907
|
-
inputCostPer1kTokens:
|
|
1908
|
-
outputCostPer1kTokens:
|
|
1909
|
-
maxOutputTokens:
|
|
1908
|
+
inputCostPer1kTokens: 5e-3,
|
|
1909
|
+
outputCostPer1kTokens: 0.025,
|
|
1910
|
+
maxOutputTokens: 128e3,
|
|
1910
1911
|
supportsStreaming: true,
|
|
1911
1912
|
isLocal: false
|
|
1912
1913
|
},
|
|
1913
|
-
"claude-opus-4-
|
|
1914
|
-
id: "claude-opus-4-
|
|
1915
|
-
name: "Claude Opus 4.
|
|
1914
|
+
"claude-opus-4-6": {
|
|
1915
|
+
id: "claude-opus-4-6",
|
|
1916
|
+
name: "Claude Opus 4.6",
|
|
1917
|
+
provider: "anthropic",
|
|
1918
|
+
contextWindow: 1e6,
|
|
1919
|
+
isVisionCapable: true,
|
|
1920
|
+
inputCostPer1kTokens: 5e-3,
|
|
1921
|
+
outputCostPer1kTokens: 0.025,
|
|
1922
|
+
maxOutputTokens: 128e3,
|
|
1923
|
+
supportsStreaming: true,
|
|
1924
|
+
isLocal: false
|
|
1925
|
+
},
|
|
1926
|
+
"claude-opus-4-5": {
|
|
1927
|
+
id: "claude-opus-4-5-20251101",
|
|
1928
|
+
name: "Claude Opus 4.5",
|
|
1916
1929
|
provider: "anthropic",
|
|
1917
1930
|
contextWindow: 2e5,
|
|
1918
1931
|
isVisionCapable: true,
|
|
1919
|
-
inputCostPer1kTokens:
|
|
1920
|
-
outputCostPer1kTokens: 0.
|
|
1921
|
-
maxOutputTokens:
|
|
1932
|
+
inputCostPer1kTokens: 5e-3,
|
|
1933
|
+
outputCostPer1kTokens: 0.025,
|
|
1934
|
+
maxOutputTokens: 64e3,
|
|
1935
|
+
supportsStreaming: true,
|
|
1936
|
+
isLocal: false
|
|
1937
|
+
},
|
|
1938
|
+
"claude-sonnet-5": {
|
|
1939
|
+
id: "claude-sonnet-5",
|
|
1940
|
+
name: "Claude Sonnet 5",
|
|
1941
|
+
provider: "anthropic",
|
|
1942
|
+
contextWindow: 1e6,
|
|
1943
|
+
isVisionCapable: true,
|
|
1944
|
+
inputCostPer1kTokens: 2e-3,
|
|
1945
|
+
outputCostPer1kTokens: 0.01,
|
|
1946
|
+
maxOutputTokens: 128e3,
|
|
1922
1947
|
supportsStreaming: true,
|
|
1923
1948
|
isLocal: false
|
|
1924
1949
|
},
|
|
@@ -1926,76 +1951,135 @@ var init_constants = __esm({
|
|
|
1926
1951
|
id: "claude-sonnet-4-6",
|
|
1927
1952
|
name: "Claude Sonnet 4.6",
|
|
1928
1953
|
provider: "anthropic",
|
|
1954
|
+
contextWindow: 1e6,
|
|
1955
|
+
isVisionCapable: true,
|
|
1956
|
+
inputCostPer1kTokens: 3e-3,
|
|
1957
|
+
outputCostPer1kTokens: 0.015,
|
|
1958
|
+
maxOutputTokens: 64e3,
|
|
1959
|
+
supportsStreaming: true,
|
|
1960
|
+
isLocal: false
|
|
1961
|
+
},
|
|
1962
|
+
"claude-sonnet-4-5": {
|
|
1963
|
+
id: "claude-sonnet-4-5-20250929",
|
|
1964
|
+
name: "Claude Sonnet 4.5",
|
|
1965
|
+
provider: "anthropic",
|
|
1929
1966
|
contextWindow: 2e5,
|
|
1930
1967
|
isVisionCapable: true,
|
|
1931
1968
|
inputCostPer1kTokens: 3e-3,
|
|
1932
1969
|
outputCostPer1kTokens: 0.015,
|
|
1933
|
-
maxOutputTokens:
|
|
1970
|
+
maxOutputTokens: 64e3,
|
|
1934
1971
|
supportsStreaming: true,
|
|
1935
1972
|
isLocal: false
|
|
1936
1973
|
},
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1974
|
+
"claude-haiku-4-5": {
|
|
1975
|
+
id: "claude-haiku-4-5-20251001",
|
|
1976
|
+
name: "Claude Haiku 4.5",
|
|
1977
|
+
provider: "anthropic",
|
|
1978
|
+
contextWindow: 2e5,
|
|
1979
|
+
isVisionCapable: true,
|
|
1980
|
+
inputCostPer1kTokens: 1e-3,
|
|
1981
|
+
outputCostPer1kTokens: 5e-3,
|
|
1982
|
+
maxOutputTokens: 64e3,
|
|
1983
|
+
supportsStreaming: true,
|
|
1984
|
+
isLocal: false
|
|
1985
|
+
},
|
|
1986
|
+
// OpenAI — active chat-capable models used by Cascade's Chat Completions path.
|
|
1987
|
+
"gpt-5.6-sol": {
|
|
1988
|
+
id: "gpt-5.6-sol",
|
|
1989
|
+
name: "GPT-5.6 Sol",
|
|
1941
1990
|
provider: "openai",
|
|
1942
|
-
contextWindow:
|
|
1991
|
+
contextWindow: 105e4,
|
|
1992
|
+
isVisionCapable: true,
|
|
1993
|
+
inputCostPer1kTokens: 4e-3,
|
|
1994
|
+
outputCostPer1kTokens: 0.02,
|
|
1995
|
+
maxOutputTokens: 128e3,
|
|
1996
|
+
supportsStreaming: true,
|
|
1997
|
+
isLocal: false
|
|
1998
|
+
},
|
|
1999
|
+
"gpt-5.6-terra": {
|
|
2000
|
+
id: "gpt-5.6-terra",
|
|
2001
|
+
name: "GPT-5.6 Terra",
|
|
2002
|
+
provider: "openai",
|
|
2003
|
+
contextWindow: 105e4,
|
|
2004
|
+
isVisionCapable: true,
|
|
2005
|
+
inputCostPer1kTokens: 2e-3,
|
|
2006
|
+
outputCostPer1kTokens: 0.012,
|
|
2007
|
+
maxOutputTokens: 128e3,
|
|
2008
|
+
supportsStreaming: true,
|
|
2009
|
+
isLocal: false
|
|
2010
|
+
},
|
|
2011
|
+
"gpt-5.6-luna": {
|
|
2012
|
+
id: "gpt-5.6-luna",
|
|
2013
|
+
name: "GPT-5.6 Luna",
|
|
2014
|
+
provider: "openai",
|
|
2015
|
+
contextWindow: 105e4,
|
|
2016
|
+
isVisionCapable: true,
|
|
2017
|
+
inputCostPer1kTokens: 2e-4,
|
|
2018
|
+
outputCostPer1kTokens: 12e-4,
|
|
2019
|
+
maxOutputTokens: 128e3,
|
|
2020
|
+
supportsStreaming: true,
|
|
2021
|
+
isLocal: false
|
|
2022
|
+
},
|
|
2023
|
+
"gpt-5.5": {
|
|
2024
|
+
id: "gpt-5.5",
|
|
2025
|
+
name: "GPT-5.5",
|
|
2026
|
+
provider: "openai",
|
|
2027
|
+
contextWindow: 105e4,
|
|
1943
2028
|
isVisionCapable: true,
|
|
1944
2029
|
inputCostPer1kTokens: 5e-3,
|
|
1945
|
-
outputCostPer1kTokens: 0.
|
|
1946
|
-
maxOutputTokens:
|
|
2030
|
+
outputCostPer1kTokens: 0.03,
|
|
2031
|
+
maxOutputTokens: 128e3,
|
|
1947
2032
|
supportsStreaming: true,
|
|
1948
2033
|
isLocal: false
|
|
1949
2034
|
},
|
|
1950
|
-
"gpt-
|
|
1951
|
-
id: "gpt-
|
|
1952
|
-
name: "GPT-
|
|
2035
|
+
"gpt-5.4": {
|
|
2036
|
+
id: "gpt-5.4",
|
|
2037
|
+
name: "GPT-5.4",
|
|
1953
2038
|
provider: "openai",
|
|
1954
|
-
contextWindow:
|
|
2039
|
+
contextWindow: 105e4,
|
|
1955
2040
|
isVisionCapable: true,
|
|
1956
|
-
inputCostPer1kTokens:
|
|
1957
|
-
outputCostPer1kTokens:
|
|
1958
|
-
maxOutputTokens:
|
|
2041
|
+
inputCostPer1kTokens: 25e-4,
|
|
2042
|
+
outputCostPer1kTokens: 0.015,
|
|
2043
|
+
maxOutputTokens: 128e3,
|
|
1959
2044
|
supportsStreaming: true,
|
|
1960
2045
|
isLocal: false
|
|
1961
2046
|
},
|
|
1962
|
-
"gpt-4
|
|
1963
|
-
id: "gpt-4
|
|
1964
|
-
name: "GPT-4
|
|
2047
|
+
"gpt-5.4-mini": {
|
|
2048
|
+
id: "gpt-5.4-mini",
|
|
2049
|
+
name: "GPT-5.4 Mini",
|
|
1965
2050
|
provider: "openai",
|
|
1966
|
-
contextWindow:
|
|
2051
|
+
contextWindow: 4e5,
|
|
1967
2052
|
isVisionCapable: true,
|
|
1968
|
-
inputCostPer1kTokens:
|
|
1969
|
-
outputCostPer1kTokens:
|
|
1970
|
-
maxOutputTokens:
|
|
2053
|
+
inputCostPer1kTokens: 75e-5,
|
|
2054
|
+
outputCostPer1kTokens: 45e-4,
|
|
2055
|
+
maxOutputTokens: 128e3,
|
|
1971
2056
|
supportsStreaming: true,
|
|
1972
2057
|
isLocal: false
|
|
1973
2058
|
},
|
|
1974
|
-
"gpt-4
|
|
1975
|
-
id: "gpt-4
|
|
1976
|
-
name: "GPT-4
|
|
2059
|
+
"gpt-5.4-nano": {
|
|
2060
|
+
id: "gpt-5.4-nano",
|
|
2061
|
+
name: "GPT-5.4 Nano",
|
|
1977
2062
|
provider: "openai",
|
|
1978
|
-
contextWindow:
|
|
2063
|
+
contextWindow: 4e5,
|
|
1979
2064
|
isVisionCapable: true,
|
|
1980
|
-
inputCostPer1kTokens:
|
|
1981
|
-
outputCostPer1kTokens:
|
|
1982
|
-
maxOutputTokens:
|
|
2065
|
+
inputCostPer1kTokens: 2e-4,
|
|
2066
|
+
outputCostPer1kTokens: 125e-5,
|
|
2067
|
+
maxOutputTokens: 128e3,
|
|
1983
2068
|
supportsStreaming: true,
|
|
1984
2069
|
isLocal: false
|
|
1985
2070
|
},
|
|
1986
|
-
"gpt-
|
|
1987
|
-
id: "gpt-
|
|
1988
|
-
name: "GPT-
|
|
2071
|
+
"gpt-5.2": {
|
|
2072
|
+
id: "gpt-5.2",
|
|
2073
|
+
name: "GPT-5.2",
|
|
1989
2074
|
provider: "openai",
|
|
1990
|
-
contextWindow:
|
|
2075
|
+
contextWindow: 4e5,
|
|
1991
2076
|
isVisionCapable: true,
|
|
1992
|
-
inputCostPer1kTokens:
|
|
1993
|
-
outputCostPer1kTokens:
|
|
1994
|
-
maxOutputTokens:
|
|
2077
|
+
inputCostPer1kTokens: 175e-5,
|
|
2078
|
+
outputCostPer1kTokens: 0.014,
|
|
2079
|
+
maxOutputTokens: 128e3,
|
|
1995
2080
|
supportsStreaming: true,
|
|
1996
2081
|
isLocal: false
|
|
1997
2082
|
},
|
|
1998
|
-
// GPT-5 family (offline baseline pricing; the live fetch keeps it current).
|
|
1999
2083
|
"gpt-5": {
|
|
2000
2084
|
id: "gpt-5",
|
|
2001
2085
|
name: "GPT-5",
|
|
@@ -2032,79 +2116,149 @@ var init_constants = __esm({
|
|
|
2032
2116
|
supportsStreaming: true,
|
|
2033
2117
|
isLocal: false
|
|
2034
2118
|
},
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
"gpt-5.5": {
|
|
2039
|
-
id: "gpt-5.5",
|
|
2040
|
-
name: "GPT-5.5",
|
|
2119
|
+
"gpt-4.1": {
|
|
2120
|
+
id: "gpt-4.1",
|
|
2121
|
+
name: "GPT-4.1",
|
|
2041
2122
|
provider: "openai",
|
|
2042
|
-
contextWindow:
|
|
2123
|
+
contextWindow: 1047576,
|
|
2043
2124
|
isVisionCapable: true,
|
|
2044
|
-
inputCostPer1kTokens:
|
|
2045
|
-
outputCostPer1kTokens:
|
|
2046
|
-
maxOutputTokens:
|
|
2125
|
+
inputCostPer1kTokens: 2e-3,
|
|
2126
|
+
outputCostPer1kTokens: 8e-3,
|
|
2127
|
+
maxOutputTokens: 32768,
|
|
2047
2128
|
supportsStreaming: true,
|
|
2048
2129
|
isLocal: false
|
|
2049
2130
|
},
|
|
2050
|
-
"gpt-
|
|
2051
|
-
id: "gpt-
|
|
2052
|
-
name: "GPT-
|
|
2131
|
+
"gpt-4.1-mini": {
|
|
2132
|
+
id: "gpt-4.1-mini",
|
|
2133
|
+
name: "GPT-4.1 Mini",
|
|
2053
2134
|
provider: "openai",
|
|
2054
|
-
contextWindow:
|
|
2135
|
+
contextWindow: 1047576,
|
|
2055
2136
|
isVisionCapable: true,
|
|
2056
|
-
inputCostPer1kTokens:
|
|
2137
|
+
inputCostPer1kTokens: 4e-4,
|
|
2138
|
+
outputCostPer1kTokens: 16e-4,
|
|
2139
|
+
maxOutputTokens: 32768,
|
|
2140
|
+
supportsStreaming: true,
|
|
2141
|
+
isLocal: false
|
|
2142
|
+
},
|
|
2143
|
+
"gpt-4.1-nano": {
|
|
2144
|
+
id: "gpt-4.1-nano",
|
|
2145
|
+
name: "GPT-4.1 Nano",
|
|
2146
|
+
provider: "openai",
|
|
2147
|
+
contextWindow: 1047576,
|
|
2148
|
+
isVisionCapable: true,
|
|
2149
|
+
inputCostPer1kTokens: 1e-4,
|
|
2150
|
+
outputCostPer1kTokens: 4e-4,
|
|
2151
|
+
maxOutputTokens: 32768,
|
|
2152
|
+
supportsStreaming: true,
|
|
2153
|
+
isLocal: false
|
|
2154
|
+
},
|
|
2155
|
+
"gpt-4o": {
|
|
2156
|
+
id: "gpt-4o",
|
|
2157
|
+
name: "GPT-4o",
|
|
2158
|
+
provider: "openai",
|
|
2159
|
+
contextWindow: 128e3,
|
|
2160
|
+
isVisionCapable: true,
|
|
2161
|
+
inputCostPer1kTokens: 25e-4,
|
|
2057
2162
|
outputCostPer1kTokens: 0.01,
|
|
2058
|
-
maxOutputTokens:
|
|
2163
|
+
maxOutputTokens: 16e3,
|
|
2059
2164
|
supportsStreaming: true,
|
|
2060
2165
|
isLocal: false
|
|
2061
2166
|
},
|
|
2062
|
-
"gpt-
|
|
2063
|
-
id: "gpt-
|
|
2064
|
-
name: "GPT-
|
|
2167
|
+
"gpt-4o-mini": {
|
|
2168
|
+
id: "gpt-4o-mini",
|
|
2169
|
+
name: "GPT-4o Mini",
|
|
2065
2170
|
provider: "openai",
|
|
2066
|
-
contextWindow:
|
|
2171
|
+
contextWindow: 128e3,
|
|
2067
2172
|
isVisionCapable: true,
|
|
2068
|
-
inputCostPer1kTokens:
|
|
2069
|
-
outputCostPer1kTokens:
|
|
2070
|
-
maxOutputTokens:
|
|
2173
|
+
inputCostPer1kTokens: 15e-5,
|
|
2174
|
+
outputCostPer1kTokens: 6e-4,
|
|
2175
|
+
maxOutputTokens: 16e3,
|
|
2071
2176
|
supportsStreaming: true,
|
|
2072
2177
|
isLocal: false
|
|
2073
2178
|
},
|
|
2074
|
-
// Google
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2179
|
+
// Google Gemini — active GA + preview chat models. Gemini 2.0/1.5 are no
|
|
2180
|
+
// longer advertised because the Gemini API shut those generations down.
|
|
2181
|
+
"gemini-3.7-flash": {
|
|
2182
|
+
id: "gemini-3.7-flash",
|
|
2183
|
+
name: "Gemini 3.7 Flash",
|
|
2078
2184
|
provider: "gemini",
|
|
2079
|
-
contextWindow:
|
|
2185
|
+
contextWindow: 1048576,
|
|
2080
2186
|
isVisionCapable: true,
|
|
2081
|
-
inputCostPer1kTokens:
|
|
2082
|
-
outputCostPer1kTokens:
|
|
2083
|
-
maxOutputTokens:
|
|
2187
|
+
inputCostPer1kTokens: 75e-5,
|
|
2188
|
+
outputCostPer1kTokens: 375e-5,
|
|
2189
|
+
maxOutputTokens: 65536,
|
|
2084
2190
|
supportsStreaming: true,
|
|
2085
2191
|
isLocal: false
|
|
2086
2192
|
},
|
|
2087
|
-
"gemini-
|
|
2088
|
-
id: "gemini-
|
|
2089
|
-
name: "Gemini
|
|
2193
|
+
"gemini-3.6-flash": {
|
|
2194
|
+
id: "gemini-3.6-flash",
|
|
2195
|
+
name: "Gemini 3.6 Flash",
|
|
2090
2196
|
provider: "gemini",
|
|
2091
|
-
contextWindow:
|
|
2197
|
+
contextWindow: 1048576,
|
|
2092
2198
|
isVisionCapable: true,
|
|
2093
|
-
inputCostPer1kTokens:
|
|
2094
|
-
outputCostPer1kTokens:
|
|
2095
|
-
maxOutputTokens:
|
|
2199
|
+
inputCostPer1kTokens: 75e-5,
|
|
2200
|
+
outputCostPer1kTokens: 375e-5,
|
|
2201
|
+
maxOutputTokens: 65536,
|
|
2096
2202
|
supportsStreaming: true,
|
|
2097
2203
|
isLocal: false
|
|
2098
2204
|
},
|
|
2099
|
-
"gemini-
|
|
2100
|
-
id: "gemini-
|
|
2101
|
-
name: "Gemini
|
|
2205
|
+
"gemini-3.5-flash": {
|
|
2206
|
+
id: "gemini-3.5-flash",
|
|
2207
|
+
name: "Gemini 3.5 Flash",
|
|
2102
2208
|
provider: "gemini",
|
|
2103
|
-
contextWindow:
|
|
2209
|
+
contextWindow: 1048576,
|
|
2104
2210
|
isVisionCapable: true,
|
|
2105
|
-
inputCostPer1kTokens:
|
|
2106
|
-
outputCostPer1kTokens:
|
|
2107
|
-
maxOutputTokens:
|
|
2211
|
+
inputCostPer1kTokens: 15e-4,
|
|
2212
|
+
outputCostPer1kTokens: 9e-3,
|
|
2213
|
+
maxOutputTokens: 65536,
|
|
2214
|
+
supportsStreaming: true,
|
|
2215
|
+
isLocal: false
|
|
2216
|
+
},
|
|
2217
|
+
"gemini-3.5-flash-lite": {
|
|
2218
|
+
id: "gemini-3.5-flash-lite",
|
|
2219
|
+
name: "Gemini 3.5 Flash-Lite",
|
|
2220
|
+
provider: "gemini",
|
|
2221
|
+
contextWindow: 1048576,
|
|
2222
|
+
isVisionCapable: true,
|
|
2223
|
+
inputCostPer1kTokens: 3e-4,
|
|
2224
|
+
outputCostPer1kTokens: 25e-4,
|
|
2225
|
+
maxOutputTokens: 65536,
|
|
2226
|
+
supportsStreaming: true,
|
|
2227
|
+
isLocal: false
|
|
2228
|
+
},
|
|
2229
|
+
"gemini-3.1-flash-lite": {
|
|
2230
|
+
id: "gemini-3.1-flash-lite",
|
|
2231
|
+
name: "Gemini 3.1 Flash-Lite",
|
|
2232
|
+
provider: "gemini",
|
|
2233
|
+
contextWindow: 1048576,
|
|
2234
|
+
isVisionCapable: true,
|
|
2235
|
+
inputCostPer1kTokens: 25e-5,
|
|
2236
|
+
outputCostPer1kTokens: 15e-4,
|
|
2237
|
+
maxOutputTokens: 65536,
|
|
2238
|
+
supportsStreaming: true,
|
|
2239
|
+
isLocal: false
|
|
2240
|
+
},
|
|
2241
|
+
"gemini-3.1-pro-preview": {
|
|
2242
|
+
id: "gemini-3.1-pro-preview",
|
|
2243
|
+
name: "Gemini 3.1 Pro Preview",
|
|
2244
|
+
provider: "gemini",
|
|
2245
|
+
contextWindow: 1048576,
|
|
2246
|
+
isVisionCapable: true,
|
|
2247
|
+
inputCostPer1kTokens: 2e-3,
|
|
2248
|
+
outputCostPer1kTokens: 0.012,
|
|
2249
|
+
maxOutputTokens: 65536,
|
|
2250
|
+
supportsStreaming: true,
|
|
2251
|
+
isLocal: false
|
|
2252
|
+
},
|
|
2253
|
+
"gemini-3-flash-preview": {
|
|
2254
|
+
id: "gemini-3-flash-preview",
|
|
2255
|
+
name: "Gemini 3 Flash Preview",
|
|
2256
|
+
provider: "gemini",
|
|
2257
|
+
contextWindow: 1048576,
|
|
2258
|
+
isVisionCapable: true,
|
|
2259
|
+
inputCostPer1kTokens: 5e-4,
|
|
2260
|
+
outputCostPer1kTokens: 3e-3,
|
|
2261
|
+
maxOutputTokens: 65536,
|
|
2108
2262
|
supportsStreaming: true,
|
|
2109
2263
|
isLocal: false
|
|
2110
2264
|
},
|
|
@@ -2112,7 +2266,7 @@ var init_constants = __esm({
|
|
|
2112
2266
|
id: "gemini-2.5-pro",
|
|
2113
2267
|
name: "Gemini 2.5 Pro",
|
|
2114
2268
|
provider: "gemini",
|
|
2115
|
-
contextWindow:
|
|
2269
|
+
contextWindow: 1048576,
|
|
2116
2270
|
isVisionCapable: true,
|
|
2117
2271
|
inputCostPer1kTokens: 125e-5,
|
|
2118
2272
|
outputCostPer1kTokens: 0.01,
|
|
@@ -2124,10 +2278,22 @@ var init_constants = __esm({
|
|
|
2124
2278
|
id: "gemini-2.5-flash",
|
|
2125
2279
|
name: "Gemini 2.5 Flash",
|
|
2126
2280
|
provider: "gemini",
|
|
2127
|
-
contextWindow:
|
|
2281
|
+
contextWindow: 1048576,
|
|
2128
2282
|
isVisionCapable: true,
|
|
2129
|
-
inputCostPer1kTokens:
|
|
2130
|
-
outputCostPer1kTokens:
|
|
2283
|
+
inputCostPer1kTokens: 3e-4,
|
|
2284
|
+
outputCostPer1kTokens: 25e-4,
|
|
2285
|
+
maxOutputTokens: 65536,
|
|
2286
|
+
supportsStreaming: true,
|
|
2287
|
+
isLocal: false
|
|
2288
|
+
},
|
|
2289
|
+
"gemini-2.5-flash-lite": {
|
|
2290
|
+
id: "gemini-2.5-flash-lite",
|
|
2291
|
+
name: "Gemini 2.5 Flash-Lite",
|
|
2292
|
+
provider: "gemini",
|
|
2293
|
+
contextWindow: 1048576,
|
|
2294
|
+
isVisionCapable: true,
|
|
2295
|
+
inputCostPer1kTokens: 1e-4,
|
|
2296
|
+
outputCostPer1kTokens: 4e-4,
|
|
2131
2297
|
maxOutputTokens: 65536,
|
|
2132
2298
|
supportsStreaming: true,
|
|
2133
2299
|
isLocal: false
|
|
@@ -2197,43 +2363,57 @@ var init_constants = __esm({
|
|
|
2197
2363
|
_m.pricingUnknown = false;
|
|
2198
2364
|
}
|
|
2199
2365
|
T1_MODEL_PRIORITY = [
|
|
2366
|
+
"gpt-5.6-sol",
|
|
2367
|
+
"claude-fable-5",
|
|
2368
|
+
"claude-opus-5",
|
|
2200
2369
|
"gpt-5.5",
|
|
2201
2370
|
"gpt-5.4",
|
|
2371
|
+
"gemini-3.1-pro-preview",
|
|
2372
|
+
"claude-opus-4-8",
|
|
2373
|
+
"claude-sonnet-5",
|
|
2374
|
+
"gemini-3.7-flash",
|
|
2375
|
+
"gpt-5.2",
|
|
2202
2376
|
"gpt-5",
|
|
2203
|
-
"claude-opus-4",
|
|
2204
|
-
"claude-sonnet-4",
|
|
2205
2377
|
"gemini-2.5-pro",
|
|
2206
2378
|
"gpt-4.1",
|
|
2207
|
-
"gpt-4o"
|
|
2208
|
-
"gemini-1.5-pro"
|
|
2379
|
+
"gpt-4o"
|
|
2209
2380
|
];
|
|
2210
2381
|
T2_MODEL_PRIORITY = [
|
|
2382
|
+
"gpt-5.6-terra",
|
|
2383
|
+
"claude-sonnet-5",
|
|
2384
|
+
"gemini-3.7-flash",
|
|
2385
|
+
"gemini-3.6-flash",
|
|
2211
2386
|
"gpt-5.4-mini",
|
|
2212
2387
|
"gpt-5-mini",
|
|
2213
|
-
"claude-sonnet-4",
|
|
2388
|
+
"claude-sonnet-4-6",
|
|
2214
2389
|
"claude-haiku-4-5",
|
|
2215
|
-
"
|
|
2390
|
+
"gemini-3.5-flash",
|
|
2216
2391
|
"gemini-2.5-flash",
|
|
2217
2392
|
"gpt-4.1-mini",
|
|
2218
2393
|
"gpt-4o-mini",
|
|
2219
|
-
"gemini-2.0-flash",
|
|
2220
2394
|
"llama3:70b"
|
|
2221
2395
|
];
|
|
2222
2396
|
T3_MODEL_PRIORITY = [
|
|
2397
|
+
"gpt-5.6-luna",
|
|
2398
|
+
"gpt-5.4-nano",
|
|
2399
|
+
"gemini-3.5-flash-lite",
|
|
2400
|
+
"gemini-3.1-flash-lite",
|
|
2401
|
+
"claude-haiku-4-5",
|
|
2223
2402
|
"gpt-5-nano",
|
|
2403
|
+
"gemini-2.5-flash-lite",
|
|
2224
2404
|
"llama3.2:3b",
|
|
2225
2405
|
"mistral:7b",
|
|
2226
|
-
"claude-haiku-4-5",
|
|
2227
|
-
"claude-haiku-3-5",
|
|
2228
2406
|
"gpt-4.1-nano",
|
|
2229
2407
|
"gpt-4o-mini",
|
|
2230
|
-
"gemini-2.5-flash"
|
|
2231
|
-
"gemini-2.0-flash"
|
|
2408
|
+
"gemini-2.5-flash"
|
|
2232
2409
|
];
|
|
2233
2410
|
VISION_MODEL_PRIORITY = [
|
|
2234
|
-
"
|
|
2411
|
+
"gpt-5.6-sol",
|
|
2412
|
+
"claude-fable-5",
|
|
2413
|
+
"claude-sonnet-5",
|
|
2414
|
+
"gemini-3.7-flash",
|
|
2235
2415
|
"gpt-4o",
|
|
2236
|
-
"gemini-2.
|
|
2416
|
+
"gemini-2.5-flash",
|
|
2237
2417
|
"llava"
|
|
2238
2418
|
];
|
|
2239
2419
|
COMPLEXITY_T2_COUNT = {
|
|
@@ -2290,8 +2470,8 @@ function normalizeEndpoint(url) {
|
|
|
2290
2470
|
if (!raw) return "";
|
|
2291
2471
|
try {
|
|
2292
2472
|
const u = new URL(raw);
|
|
2293
|
-
const
|
|
2294
|
-
return `${u.protocol}//${u.host.toLowerCase()}${
|
|
2473
|
+
const path41 = stripTrailingSlashes(`${u.pathname}${u.search}`);
|
|
2474
|
+
return `${u.protocol}//${u.host.toLowerCase()}${path41}`;
|
|
2295
2475
|
} catch {
|
|
2296
2476
|
return raw.toLowerCase();
|
|
2297
2477
|
}
|
|
@@ -2423,7 +2603,7 @@ var CLIENT_VERSION_SEGMENT, REDIRECT_STATUSES, NULL_BODY_STATUSES, MAX_REDIRECTS
|
|
|
2423
2603
|
var init_net = __esm({
|
|
2424
2604
|
"src/utils/net.ts"() {
|
|
2425
2605
|
try {
|
|
2426
|
-
|
|
2606
|
+
dnsCallback__default.default.setDefaultResultOrder("ipv4first");
|
|
2427
2607
|
} catch {
|
|
2428
2608
|
}
|
|
2429
2609
|
CLIENT_VERSION_SEGMENT = {
|
|
@@ -3155,6 +3335,56 @@ var init_openai = __esm({
|
|
|
3155
3335
|
}
|
|
3156
3336
|
});
|
|
3157
3337
|
|
|
3338
|
+
// src/providers/cloud-model-catalog.json
|
|
3339
|
+
var cloud_model_catalog_default;
|
|
3340
|
+
var init_cloud_model_catalog = __esm({
|
|
3341
|
+
"src/providers/cloud-model-catalog.json"() {
|
|
3342
|
+
cloud_model_catalog_default = {
|
|
3343
|
+
schemaVersion: 1,
|
|
3344
|
+
verifiedAt: "2026-08-27",
|
|
3345
|
+
scope: "GA and Preview text/chat models that Cascade can route through its maintained cloud providers. Retired, shutdown, realtime/audio-only, embedding, image-only, video-only, and access-restricted models are excluded.",
|
|
3346
|
+
note: "Capabilities belong to the canonical model. Pricing deliberately does not live here: Cascade resolves price by model x provider x region in core/router/pricing-data.json. A model exposed by multiple providers may therefore have different prices without duplicating its capability profile.",
|
|
3347
|
+
models: [
|
|
3348
|
+
{ id: "gpt-5.6-sol", name: "GPT-5.6 Sol", providers: ["openai", "azure"], lifecycle: "ga", contextWindow: 105e4, maxOutputTokens: 128e3, vision: true, toolUse: true },
|
|
3349
|
+
{ id: "gpt-5.6-terra", name: "GPT-5.6 Terra", providers: ["openai", "azure"], lifecycle: "ga", contextWindow: 105e4, maxOutputTokens: 128e3, vision: true, toolUse: true },
|
|
3350
|
+
{ id: "gpt-5.6-luna", name: "GPT-5.6 Luna", providers: ["openai", "azure"], lifecycle: "ga", contextWindow: 105e4, maxOutputTokens: 128e3, vision: true, toolUse: true },
|
|
3351
|
+
{ id: "gpt-5.5", name: "GPT-5.5", providers: ["openai", "azure"], lifecycle: "ga", contextWindow: 105e4, maxOutputTokens: 128e3, vision: true, toolUse: true },
|
|
3352
|
+
{ id: "gpt-5.4", name: "GPT-5.4", providers: ["openai", "azure"], lifecycle: "ga", contextWindow: 105e4, maxOutputTokens: 128e3, vision: true, toolUse: true },
|
|
3353
|
+
{ id: "gpt-5.4-mini", name: "GPT-5.4 Mini", providers: ["openai", "azure"], lifecycle: "ga", contextWindow: 4e5, maxOutputTokens: 128e3, vision: true, toolUse: true },
|
|
3354
|
+
{ id: "gpt-5.4-nano", name: "GPT-5.4 Nano", providers: ["openai", "azure"], lifecycle: "ga", contextWindow: 4e5, maxOutputTokens: 128e3, vision: true, toolUse: true },
|
|
3355
|
+
{ id: "gpt-5", name: "GPT-5", providers: ["openai", "azure"], lifecycle: "ga", contextWindow: 4e5, maxOutputTokens: 128e3, vision: true, toolUse: true },
|
|
3356
|
+
{ id: "gpt-5-mini", name: "GPT-5 Mini", providers: ["openai", "azure"], lifecycle: "ga", contextWindow: 4e5, maxOutputTokens: 128e3, vision: true, toolUse: true },
|
|
3357
|
+
{ id: "gpt-5-nano", name: "GPT-5 Nano", providers: ["openai", "azure"], lifecycle: "ga", contextWindow: 4e5, maxOutputTokens: 128e3, vision: true, toolUse: true },
|
|
3358
|
+
{ id: "gpt-4.1", name: "GPT-4.1", providers: ["openai", "azure"], lifecycle: "ga", contextWindow: 1047576, maxOutputTokens: 32768, vision: true, toolUse: true },
|
|
3359
|
+
{ id: "gpt-4.1-mini", name: "GPT-4.1 Mini", providers: ["openai", "azure"], lifecycle: "ga", contextWindow: 1047576, maxOutputTokens: 32768, vision: true, toolUse: true },
|
|
3360
|
+
{ id: "gpt-4.1-nano", name: "GPT-4.1 Nano", providers: ["openai", "azure"], lifecycle: "ga", contextWindow: 1047576, maxOutputTokens: 32768, vision: true, toolUse: true },
|
|
3361
|
+
{ id: "gpt-4o", name: "GPT-4o", providers: ["openai", "azure"], lifecycle: "ga", contextWindow: 128e3, maxOutputTokens: 16384, vision: true, toolUse: true },
|
|
3362
|
+
{ id: "gpt-4o-mini", name: "GPT-4o Mini", providers: ["openai", "azure"], lifecycle: "ga", contextWindow: 128e3, maxOutputTokens: 16384, vision: true, toolUse: true },
|
|
3363
|
+
{ id: "claude-fable-5", name: "Claude Fable 5", providers: ["anthropic"], lifecycle: "ga", contextWindow: 1e6, maxOutputTokens: 128e3, vision: true, toolUse: true },
|
|
3364
|
+
{ id: "claude-opus-5", name: "Claude Opus 5", providers: ["anthropic"], lifecycle: "ga", contextWindow: 1e6, maxOutputTokens: 128e3, vision: true, toolUse: true },
|
|
3365
|
+
{ id: "claude-opus-4-8", name: "Claude Opus 4.8", providers: ["anthropic"], lifecycle: "ga", contextWindow: 1e6, maxOutputTokens: 128e3, vision: true, toolUse: true },
|
|
3366
|
+
{ id: "claude-opus-4-7", name: "Claude Opus 4.7", providers: ["anthropic"], lifecycle: "ga", contextWindow: 1e6, maxOutputTokens: 128e3, vision: true, toolUse: true },
|
|
3367
|
+
{ id: "claude-opus-4-6", name: "Claude Opus 4.6", providers: ["anthropic"], lifecycle: "ga", contextWindow: 1e6, vision: true, toolUse: true },
|
|
3368
|
+
{ id: "claude-opus-4-5-20251101", name: "Claude Opus 4.5", providers: ["anthropic"], lifecycle: "ga", contextWindow: 2e5, vision: true, toolUse: true },
|
|
3369
|
+
{ id: "claude-sonnet-5", name: "Claude Sonnet 5", providers: ["anthropic"], lifecycle: "ga", contextWindow: 1e6, maxOutputTokens: 128e3, vision: true, toolUse: true },
|
|
3370
|
+
{ id: "claude-sonnet-4-6", name: "Claude Sonnet 4.6", providers: ["anthropic"], lifecycle: "ga", contextWindow: 1e6, maxOutputTokens: 128e3, vision: true, toolUse: true },
|
|
3371
|
+
{ id: "claude-sonnet-4-5-20250929", name: "Claude Sonnet 4.5", providers: ["anthropic"], lifecycle: "ga", contextWindow: 2e5, vision: true, toolUse: true },
|
|
3372
|
+
{ id: "claude-haiku-4-5-20251001", name: "Claude Haiku 4.5", providers: ["anthropic"], lifecycle: "ga", contextWindow: 2e5, maxOutputTokens: 64e3, vision: true, toolUse: true },
|
|
3373
|
+
{ id: "gemini-3.7-flash", name: "Gemini 3.7 Flash", providers: ["gemini"], lifecycle: "ga", contextWindow: 1048576, maxOutputTokens: 65536, vision: true, toolUse: true },
|
|
3374
|
+
{ id: "gemini-3.6-flash", name: "Gemini 3.6 Flash", providers: ["gemini"], lifecycle: "ga", contextWindow: 1048576, maxOutputTokens: 65536, vision: true, toolUse: true },
|
|
3375
|
+
{ id: "gemini-3.5-flash", name: "Gemini 3.5 Flash", providers: ["gemini"], lifecycle: "ga", contextWindow: 1048576, maxOutputTokens: 65536, vision: true, toolUse: true },
|
|
3376
|
+
{ id: "gemini-3.5-flash-lite", name: "Gemini 3.5 Flash-Lite", providers: ["gemini"], lifecycle: "ga", contextWindow: 1048576, maxOutputTokens: 65536, vision: true, toolUse: true },
|
|
3377
|
+
{ id: "gemini-3.1-flash-lite", name: "Gemini 3.1 Flash-Lite", providers: ["gemini"], lifecycle: "ga", contextWindow: 1048576, maxOutputTokens: 65536, vision: true, toolUse: true },
|
|
3378
|
+
{ id: "gemini-3.1-pro-preview", name: "Gemini 3.1 Pro", providers: ["gemini"], lifecycle: "preview", contextWindow: 1048576, maxOutputTokens: 65536, vision: true, toolUse: true },
|
|
3379
|
+
{ id: "gemini-3-flash-preview", name: "Gemini 3 Flash", providers: ["gemini"], lifecycle: "preview", contextWindow: 1048576, maxOutputTokens: 65536, vision: true, toolUse: true },
|
|
3380
|
+
{ id: "gemini-2.5-pro", name: "Gemini 2.5 Pro", providers: ["gemini"], lifecycle: "ga", contextWindow: 1048576, maxOutputTokens: 65536, vision: true, toolUse: true },
|
|
3381
|
+
{ id: "gemini-2.5-flash", name: "Gemini 2.5 Flash", providers: ["gemini"], lifecycle: "ga", contextWindow: 1048576, maxOutputTokens: 65536, vision: true, toolUse: true },
|
|
3382
|
+
{ id: "gemini-2.5-flash-lite", name: "Gemini 2.5 Flash-Lite", providers: ["gemini"], lifecycle: "ga", contextWindow: 1048576, maxOutputTokens: 65536, vision: true, toolUse: true }
|
|
3383
|
+
]
|
|
3384
|
+
};
|
|
3385
|
+
}
|
|
3386
|
+
});
|
|
3387
|
+
|
|
3158
3388
|
// src/providers/azure.ts
|
|
3159
3389
|
var azure_exports = {};
|
|
3160
3390
|
__export(azure_exports, {
|
|
@@ -3163,36 +3393,81 @@ __export(azure_exports, {
|
|
|
3163
3393
|
azureModelForDeployment: () => azureModelForDeployment,
|
|
3164
3394
|
inferAzureBaseModel: () => inferAzureBaseModel
|
|
3165
3395
|
});
|
|
3396
|
+
function compactModelId(id) {
|
|
3397
|
+
return id.toLowerCase().replace(/[^a-z0-9.]/g, "");
|
|
3398
|
+
}
|
|
3399
|
+
function catalogEntry(id) {
|
|
3400
|
+
const n = id.toLowerCase();
|
|
3401
|
+
return CLOUD_MODELS.find((m) => m.id.toLowerCase() === n);
|
|
3402
|
+
}
|
|
3166
3403
|
function inferAzureBaseModel(deploymentName) {
|
|
3167
3404
|
const n = deploymentName.toLowerCase();
|
|
3168
|
-
|
|
3405
|
+
const compact = compactModelId(n);
|
|
3406
|
+
const hasBareGpt56Alias = compact.includes("gpt5.6");
|
|
3407
|
+
for (const model of AZURE_CATALOG) {
|
|
3408
|
+
if (hasBareGpt56Alias && model.id === "gpt-5") continue;
|
|
3409
|
+
if (n.includes(model.id.toLowerCase()) || compact.includes(compactModelId(model.id))) {
|
|
3410
|
+
return model.id;
|
|
3411
|
+
}
|
|
3412
|
+
}
|
|
3413
|
+
if (hasBareGpt56Alias) return "gpt-5.6-sol";
|
|
3414
|
+
const gpt5At = compact.indexOf("gpt5");
|
|
3415
|
+
if (gpt5At !== -1) {
|
|
3416
|
+
const suffix = compact.slice(gpt5At + "gpt5".length);
|
|
3417
|
+
if (suffix.includes("nano")) return "gpt-5-nano";
|
|
3418
|
+
if (suffix.includes("mini")) return "gpt-5-mini";
|
|
3419
|
+
return "gpt-5";
|
|
3420
|
+
}
|
|
3421
|
+
if (compact.includes("gpt4.1nano")) return "gpt-4.1-nano";
|
|
3422
|
+
if (compact.includes("gpt4.1mini")) return "gpt-4.1-mini";
|
|
3423
|
+
if (compact.includes("gpt4.1")) return "gpt-4.1";
|
|
3424
|
+
if (compact.includes("gpt4omini")) return "gpt-4o-mini";
|
|
3425
|
+
if (compact.includes("gpt4o")) return "gpt-4o";
|
|
3169
3426
|
return null;
|
|
3170
3427
|
}
|
|
3428
|
+
function catalogModelInfo(baseModelId) {
|
|
3429
|
+
const entry = catalogEntry(baseModelId);
|
|
3430
|
+
if (!entry?.contextWindow) return void 0;
|
|
3431
|
+
return {
|
|
3432
|
+
id: entry.id,
|
|
3433
|
+
name: entry.name,
|
|
3434
|
+
provider: "openai",
|
|
3435
|
+
contextWindow: entry.contextWindow,
|
|
3436
|
+
isVisionCapable: entry.vision ?? false,
|
|
3437
|
+
inputCostPer1kTokens: 0,
|
|
3438
|
+
outputCostPer1kTokens: 0,
|
|
3439
|
+
maxOutputTokens: entry.maxOutputTokens ?? 16e3,
|
|
3440
|
+
supportsStreaming: true,
|
|
3441
|
+
isLocal: false,
|
|
3442
|
+
supportsToolUse: entry.toolUse ?? true,
|
|
3443
|
+
pricingUnknown: true
|
|
3444
|
+
};
|
|
3445
|
+
}
|
|
3171
3446
|
function azureModelForDeployment(cfg) {
|
|
3172
3447
|
if (cfg.type !== "azure" || !cfg.deploymentName?.trim()) return null;
|
|
3173
3448
|
const id = cfg.deploymentName.trim();
|
|
3174
3449
|
const name = cfg.label?.trim() || id;
|
|
3175
3450
|
const baseModelId = cfg.model?.trim() || inferAzureBaseModel(id) || void 0;
|
|
3176
|
-
const base = baseModelId ? MODELS[baseModelId] : void 0;
|
|
3177
|
-
if (base) {
|
|
3451
|
+
const base = baseModelId ? MODELS[baseModelId] ?? catalogModelInfo(baseModelId) : void 0;
|
|
3452
|
+
if (base && baseModelId) {
|
|
3178
3453
|
const azurePrice = resolvePricing(
|
|
3179
3454
|
{ id, provider: "azure", isLocal: false, baseModelId },
|
|
3180
3455
|
{ region: cfg.region }
|
|
3181
3456
|
);
|
|
3457
|
+
const exactAzurePrice = !azurePrice.unknown && !azurePrice.estimatedFromProvider;
|
|
3458
|
+
const nativeToolsOnThisTransport = /^gpt-5\.6-(?:sol|terra|luna)$/i.test(baseModelId) ? false : base.supportsToolUse ?? true;
|
|
3182
3459
|
return {
|
|
3183
3460
|
...base,
|
|
3184
3461
|
id,
|
|
3185
|
-
// callable deployment name
|
|
3186
3462
|
name,
|
|
3187
3463
|
provider: "azure",
|
|
3188
3464
|
baseModelId,
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
...azurePrice.unknown ? {} : {
|
|
3465
|
+
supportsToolUse: nativeToolsOnThisTransport,
|
|
3466
|
+
...!azurePrice.unknown ? {
|
|
3192
3467
|
inputCostPer1kTokens: azurePrice.input,
|
|
3193
3468
|
outputCostPer1kTokens: azurePrice.output,
|
|
3194
|
-
pricingUnknown:
|
|
3195
|
-
}
|
|
3469
|
+
pricingUnknown: !exactAzurePrice
|
|
3470
|
+
} : { pricingUnknown: true }
|
|
3196
3471
|
};
|
|
3197
3472
|
}
|
|
3198
3473
|
return {
|
|
@@ -3207,39 +3482,34 @@ function azureModelForDeployment(cfg) {
|
|
|
3207
3482
|
maxOutputTokens: 16e3,
|
|
3208
3483
|
supportsStreaming: true,
|
|
3209
3484
|
isLocal: false,
|
|
3210
|
-
supportsToolUse: true
|
|
3485
|
+
supportsToolUse: true,
|
|
3486
|
+
pricingUnknown: true
|
|
3211
3487
|
};
|
|
3212
3488
|
}
|
|
3213
|
-
|
|
3489
|
+
function stripTrailingSlashes3(value) {
|
|
3490
|
+
let end = value.length;
|
|
3491
|
+
while (end > 0 && value.charCodeAt(end - 1) === 47) end--;
|
|
3492
|
+
return value.slice(0, end);
|
|
3493
|
+
}
|
|
3494
|
+
var DEFAULT_AZURE_API_VERSION, CLOUD_MODELS, AZURE_CATALOG, AZURE_BASE_MODELS, AzureOpenAIProvider;
|
|
3214
3495
|
var init_azure = __esm({
|
|
3215
3496
|
"src/providers/azure.ts"() {
|
|
3216
3497
|
init_constants();
|
|
3217
3498
|
init_openai();
|
|
3218
3499
|
init_pricing();
|
|
3500
|
+
init_cloud_model_catalog();
|
|
3219
3501
|
DEFAULT_AZURE_API_VERSION = "2024-12-01-preview";
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
[/gpt-?5\.4/, "gpt-5.4"],
|
|
3224
|
-
[/gpt-?5.*nano/, "gpt-5-nano"],
|
|
3225
|
-
[/gpt-?5.*mini/, "gpt-5-mini"],
|
|
3226
|
-
[/gpt-?5/, "gpt-5"],
|
|
3227
|
-
[/gpt-?4\.1-nano/, "gpt-4.1-nano"],
|
|
3228
|
-
[/gpt-?4\.1-mini/, "gpt-4.1-mini"],
|
|
3229
|
-
[/gpt-?4\.1/, "gpt-4.1"],
|
|
3230
|
-
[/gpt-?4o-mini/, "gpt-4o-mini"],
|
|
3231
|
-
[/gpt-?4o/, "gpt-4o"]
|
|
3232
|
-
];
|
|
3233
|
-
AZURE_BASE_MODELS = AZURE_BASE_MODEL_RULES.map(([, id]) => id);
|
|
3502
|
+
CLOUD_MODELS = cloud_model_catalog_default.models;
|
|
3503
|
+
AZURE_CATALOG = CLOUD_MODELS.filter((m) => m.providers.includes("azure")).slice().sort((a, b) => b.id.length - a.id.length || a.id.localeCompare(b.id));
|
|
3504
|
+
AZURE_BASE_MODELS = AZURE_CATALOG.map((m) => m.id);
|
|
3234
3505
|
AzureOpenAIProvider = class extends OpenAIProvider {
|
|
3235
3506
|
constructor(config, model) {
|
|
3236
3507
|
const rawUrl = config.baseUrl ?? AZURE_BASE_URL_TEMPLATE.replace("{resource}", "YOUR_RESOURCE");
|
|
3237
|
-
const endpoint = rawUrl
|
|
3508
|
+
const endpoint = stripTrailingSlashes3(rawUrl);
|
|
3238
3509
|
super(
|
|
3239
3510
|
{
|
|
3240
3511
|
...config,
|
|
3241
3512
|
baseUrl: endpoint
|
|
3242
|
-
// Kept for superclass compatibility if it reads it
|
|
3243
3513
|
},
|
|
3244
3514
|
model
|
|
3245
3515
|
);
|
|
@@ -4223,16 +4493,16 @@ var require_isarray = __commonJS({
|
|
|
4223
4493
|
}
|
|
4224
4494
|
});
|
|
4225
4495
|
|
|
4226
|
-
// node_modules/
|
|
4496
|
+
// node_modules/readable-stream/lib/internal/streams/stream.js
|
|
4227
4497
|
var require_stream = __commonJS({
|
|
4228
|
-
"node_modules/
|
|
4498
|
+
"node_modules/readable-stream/lib/internal/streams/stream.js"(exports, module) {
|
|
4229
4499
|
module.exports = __require("stream");
|
|
4230
4500
|
}
|
|
4231
4501
|
});
|
|
4232
4502
|
|
|
4233
|
-
// node_modules/
|
|
4503
|
+
// node_modules/readable-stream/node_modules/safe-buffer/index.js
|
|
4234
4504
|
var require_safe_buffer = __commonJS({
|
|
4235
|
-
"node_modules/
|
|
4505
|
+
"node_modules/readable-stream/node_modules/safe-buffer/index.js"(exports, module) {
|
|
4236
4506
|
var buffer = __require("buffer");
|
|
4237
4507
|
var Buffer2 = buffer.Buffer;
|
|
4238
4508
|
function copyProps(src, dst) {
|
|
@@ -4350,7 +4620,7 @@ var require_util = __commonJS({
|
|
|
4350
4620
|
typeof arg === "undefined";
|
|
4351
4621
|
}
|
|
4352
4622
|
exports.isPrimitive = isPrimitive;
|
|
4353
|
-
exports.isBuffer = Buffer.isBuffer;
|
|
4623
|
+
exports.isBuffer = __require("buffer").Buffer.isBuffer;
|
|
4354
4624
|
function objectToString(o) {
|
|
4355
4625
|
return Object.prototype.toString.call(o);
|
|
4356
4626
|
}
|
|
@@ -4403,9 +4673,9 @@ var require_inherits = __commonJS({
|
|
|
4403
4673
|
}
|
|
4404
4674
|
});
|
|
4405
4675
|
|
|
4406
|
-
// node_modules/
|
|
4676
|
+
// node_modules/readable-stream/lib/internal/streams/BufferList.js
|
|
4407
4677
|
var require_BufferList = __commonJS({
|
|
4408
|
-
"node_modules/
|
|
4678
|
+
"node_modules/readable-stream/lib/internal/streams/BufferList.js"(exports, module) {
|
|
4409
4679
|
function _classCallCheck(instance, Constructor) {
|
|
4410
4680
|
if (!(instance instanceof Constructor)) {
|
|
4411
4681
|
throw new TypeError("Cannot call a class as a function");
|
|
@@ -4480,9 +4750,9 @@ var require_BufferList = __commonJS({
|
|
|
4480
4750
|
}
|
|
4481
4751
|
});
|
|
4482
4752
|
|
|
4483
|
-
// node_modules/
|
|
4753
|
+
// node_modules/readable-stream/lib/internal/streams/destroy.js
|
|
4484
4754
|
var require_destroy = __commonJS({
|
|
4485
|
-
"node_modules/
|
|
4755
|
+
"node_modules/readable-stream/lib/internal/streams/destroy.js"(exports, module) {
|
|
4486
4756
|
var pna = require_process_nextick_args();
|
|
4487
4757
|
function destroy(err, cb) {
|
|
4488
4758
|
var _this = this;
|
|
@@ -4555,9 +4825,9 @@ var require_node = __commonJS({
|
|
|
4555
4825
|
}
|
|
4556
4826
|
});
|
|
4557
4827
|
|
|
4558
|
-
// node_modules/
|
|
4828
|
+
// node_modules/readable-stream/lib/_stream_writable.js
|
|
4559
4829
|
var require_stream_writable = __commonJS({
|
|
4560
|
-
"node_modules/
|
|
4830
|
+
"node_modules/readable-stream/lib/_stream_writable.js"(exports, module) {
|
|
4561
4831
|
var pna = require_process_nextick_args();
|
|
4562
4832
|
module.exports = Writable;
|
|
4563
4833
|
function CorkedRequest(state) {
|
|
@@ -4994,9 +5264,9 @@ var require_stream_writable = __commonJS({
|
|
|
4994
5264
|
}
|
|
4995
5265
|
});
|
|
4996
5266
|
|
|
4997
|
-
// node_modules/
|
|
5267
|
+
// node_modules/readable-stream/lib/_stream_duplex.js
|
|
4998
5268
|
var require_stream_duplex = __commonJS({
|
|
4999
|
-
"node_modules/
|
|
5269
|
+
"node_modules/readable-stream/lib/_stream_duplex.js"(exports, module) {
|
|
5000
5270
|
var pna = require_process_nextick_args();
|
|
5001
5271
|
var objectKeys = Object.keys || function(obj) {
|
|
5002
5272
|
var keys2 = [];
|
|
@@ -5070,10 +5340,67 @@ var require_stream_duplex = __commonJS({
|
|
|
5070
5340
|
}
|
|
5071
5341
|
});
|
|
5072
5342
|
|
|
5073
|
-
// node_modules/
|
|
5343
|
+
// node_modules/string_decoder/node_modules/safe-buffer/index.js
|
|
5344
|
+
var require_safe_buffer2 = __commonJS({
|
|
5345
|
+
"node_modules/string_decoder/node_modules/safe-buffer/index.js"(exports, module) {
|
|
5346
|
+
var buffer = __require("buffer");
|
|
5347
|
+
var Buffer2 = buffer.Buffer;
|
|
5348
|
+
function copyProps(src, dst) {
|
|
5349
|
+
for (var key in src) {
|
|
5350
|
+
dst[key] = src[key];
|
|
5351
|
+
}
|
|
5352
|
+
}
|
|
5353
|
+
if (Buffer2.from && Buffer2.alloc && Buffer2.allocUnsafe && Buffer2.allocUnsafeSlow) {
|
|
5354
|
+
module.exports = buffer;
|
|
5355
|
+
} else {
|
|
5356
|
+
copyProps(buffer, exports);
|
|
5357
|
+
exports.Buffer = SafeBuffer;
|
|
5358
|
+
}
|
|
5359
|
+
function SafeBuffer(arg, encodingOrOffset, length) {
|
|
5360
|
+
return Buffer2(arg, encodingOrOffset, length);
|
|
5361
|
+
}
|
|
5362
|
+
copyProps(Buffer2, SafeBuffer);
|
|
5363
|
+
SafeBuffer.from = function(arg, encodingOrOffset, length) {
|
|
5364
|
+
if (typeof arg === "number") {
|
|
5365
|
+
throw new TypeError("Argument must not be a number");
|
|
5366
|
+
}
|
|
5367
|
+
return Buffer2(arg, encodingOrOffset, length);
|
|
5368
|
+
};
|
|
5369
|
+
SafeBuffer.alloc = function(size, fill, encoding) {
|
|
5370
|
+
if (typeof size !== "number") {
|
|
5371
|
+
throw new TypeError("Argument must be a number");
|
|
5372
|
+
}
|
|
5373
|
+
var buf = Buffer2(size);
|
|
5374
|
+
if (fill !== void 0) {
|
|
5375
|
+
if (typeof encoding === "string") {
|
|
5376
|
+
buf.fill(fill, encoding);
|
|
5377
|
+
} else {
|
|
5378
|
+
buf.fill(fill);
|
|
5379
|
+
}
|
|
5380
|
+
} else {
|
|
5381
|
+
buf.fill(0);
|
|
5382
|
+
}
|
|
5383
|
+
return buf;
|
|
5384
|
+
};
|
|
5385
|
+
SafeBuffer.allocUnsafe = function(size) {
|
|
5386
|
+
if (typeof size !== "number") {
|
|
5387
|
+
throw new TypeError("Argument must be a number");
|
|
5388
|
+
}
|
|
5389
|
+
return Buffer2(size);
|
|
5390
|
+
};
|
|
5391
|
+
SafeBuffer.allocUnsafeSlow = function(size) {
|
|
5392
|
+
if (typeof size !== "number") {
|
|
5393
|
+
throw new TypeError("Argument must be a number");
|
|
5394
|
+
}
|
|
5395
|
+
return buffer.SlowBuffer(size);
|
|
5396
|
+
};
|
|
5397
|
+
}
|
|
5398
|
+
});
|
|
5399
|
+
|
|
5400
|
+
// node_modules/string_decoder/lib/string_decoder.js
|
|
5074
5401
|
var require_string_decoder = __commonJS({
|
|
5075
|
-
"node_modules/
|
|
5076
|
-
var Buffer2 =
|
|
5402
|
+
"node_modules/string_decoder/lib/string_decoder.js"(exports) {
|
|
5403
|
+
var Buffer2 = require_safe_buffer2().Buffer;
|
|
5077
5404
|
var isEncoding = Buffer2.isEncoding || function(encoding) {
|
|
5078
5405
|
encoding = "" + encoding;
|
|
5079
5406
|
switch (encoding && encoding.toLowerCase()) {
|
|
@@ -5307,9 +5634,9 @@ var require_string_decoder = __commonJS({
|
|
|
5307
5634
|
}
|
|
5308
5635
|
});
|
|
5309
5636
|
|
|
5310
|
-
// node_modules/
|
|
5637
|
+
// node_modules/readable-stream/lib/_stream_readable.js
|
|
5311
5638
|
var require_stream_readable = __commonJS({
|
|
5312
|
-
"node_modules/
|
|
5639
|
+
"node_modules/readable-stream/lib/_stream_readable.js"(exports, module) {
|
|
5313
5640
|
var pna = require_process_nextick_args();
|
|
5314
5641
|
module.exports = Readable2;
|
|
5315
5642
|
var isArray = require_isarray();
|
|
@@ -5992,9 +6319,9 @@ var require_stream_readable = __commonJS({
|
|
|
5992
6319
|
}
|
|
5993
6320
|
});
|
|
5994
6321
|
|
|
5995
|
-
// node_modules/
|
|
6322
|
+
// node_modules/readable-stream/lib/_stream_transform.js
|
|
5996
6323
|
var require_stream_transform = __commonJS({
|
|
5997
|
-
"node_modules/
|
|
6324
|
+
"node_modules/readable-stream/lib/_stream_transform.js"(exports, module) {
|
|
5998
6325
|
module.exports = Transform;
|
|
5999
6326
|
var Duplex = require_stream_duplex();
|
|
6000
6327
|
var util = Object.create(require_util());
|
|
@@ -6091,9 +6418,9 @@ var require_stream_transform = __commonJS({
|
|
|
6091
6418
|
}
|
|
6092
6419
|
});
|
|
6093
6420
|
|
|
6094
|
-
// node_modules/
|
|
6421
|
+
// node_modules/readable-stream/lib/_stream_passthrough.js
|
|
6095
6422
|
var require_stream_passthrough = __commonJS({
|
|
6096
|
-
"node_modules/
|
|
6423
|
+
"node_modules/readable-stream/lib/_stream_passthrough.js"(exports, module) {
|
|
6097
6424
|
module.exports = PassThrough;
|
|
6098
6425
|
var Transform = require_stream_transform();
|
|
6099
6426
|
var util = Object.create(require_util());
|
|
@@ -6109,9 +6436,9 @@ var require_stream_passthrough = __commonJS({
|
|
|
6109
6436
|
}
|
|
6110
6437
|
});
|
|
6111
6438
|
|
|
6112
|
-
// node_modules/
|
|
6439
|
+
// node_modules/readable-stream/readable.js
|
|
6113
6440
|
var require_readable = __commonJS({
|
|
6114
|
-
"node_modules/
|
|
6441
|
+
"node_modules/readable-stream/readable.js"(exports, module) {
|
|
6115
6442
|
var Stream = __require("stream");
|
|
6116
6443
|
if (process.env.READABLE_STREAM === "disable" && Stream) {
|
|
6117
6444
|
module.exports = Stream;
|
|
@@ -7020,8 +7347,8 @@ var require_utils = __commonJS({
|
|
|
7020
7347
|
var result = transform[inputType][outputType](input);
|
|
7021
7348
|
return result;
|
|
7022
7349
|
};
|
|
7023
|
-
exports.resolve = function(
|
|
7024
|
-
var parts =
|
|
7350
|
+
exports.resolve = function(path41) {
|
|
7351
|
+
var parts = path41.split("/");
|
|
7025
7352
|
var result = [];
|
|
7026
7353
|
for (var index = 0; index < parts.length; index++) {
|
|
7027
7354
|
var part = parts[index];
|
|
@@ -12836,18 +13163,18 @@ var require_object = __commonJS({
|
|
|
12836
13163
|
var object = new ZipObject(name, zipObjectContent, o);
|
|
12837
13164
|
this.files[name] = object;
|
|
12838
13165
|
};
|
|
12839
|
-
var parentFolder = function(
|
|
12840
|
-
if (
|
|
12841
|
-
|
|
13166
|
+
var parentFolder = function(path41) {
|
|
13167
|
+
if (path41.slice(-1) === "/") {
|
|
13168
|
+
path41 = path41.substring(0, path41.length - 1);
|
|
12842
13169
|
}
|
|
12843
|
-
var lastSlash =
|
|
12844
|
-
return lastSlash > 0 ?
|
|
13170
|
+
var lastSlash = path41.lastIndexOf("/");
|
|
13171
|
+
return lastSlash > 0 ? path41.substring(0, lastSlash) : "";
|
|
12845
13172
|
};
|
|
12846
|
-
var forceTrailingSlash = function(
|
|
12847
|
-
if (
|
|
12848
|
-
|
|
13173
|
+
var forceTrailingSlash = function(path41) {
|
|
13174
|
+
if (path41.slice(-1) !== "/") {
|
|
13175
|
+
path41 += "/";
|
|
12849
13176
|
}
|
|
12850
|
-
return
|
|
13177
|
+
return path41;
|
|
12851
13178
|
};
|
|
12852
13179
|
var folderAdd = function(name, createFolders) {
|
|
12853
13180
|
createFolders = typeof createFolders !== "undefined" ? createFolders : defaults.createFolders;
|
|
@@ -13846,12 +14173,12 @@ var init_audit_logger = __esm({
|
|
|
13846
14173
|
constructor(workspacePath, debugMode = false) {
|
|
13847
14174
|
this.workspacePath = workspacePath;
|
|
13848
14175
|
this.debugMode = debugMode;
|
|
13849
|
-
const cascadeDir =
|
|
13850
|
-
if (!
|
|
13851
|
-
|
|
14176
|
+
const cascadeDir = path36__default.default.join(workspacePath, ".cascade");
|
|
14177
|
+
if (!fs33__default.default.existsSync(cascadeDir)) {
|
|
14178
|
+
fs33__default.default.mkdirSync(cascadeDir, { recursive: true });
|
|
13852
14179
|
}
|
|
13853
|
-
this.keyPath =
|
|
13854
|
-
this.dbPath =
|
|
14180
|
+
this.keyPath = path36__default.default.join(cascadeDir, "audit_log.key");
|
|
14181
|
+
this.dbPath = path36__default.default.join(cascadeDir, "audit_log.db");
|
|
13855
14182
|
this.initEncryptionKey();
|
|
13856
14183
|
this.db = new Database2__default.default(this.dbPath);
|
|
13857
14184
|
this.db.pragma("journal_mode = WAL");
|
|
@@ -13881,11 +14208,11 @@ var init_audit_logger = __esm({
|
|
|
13881
14208
|
return crypto__default.default.createHash("sha256").update(`${prevHash}|${timestamp}|${eventType}|${tierId}|${encryptedPayload}`).digest("hex");
|
|
13882
14209
|
}
|
|
13883
14210
|
initEncryptionKey() {
|
|
13884
|
-
if (
|
|
13885
|
-
this.encryptionKey =
|
|
14211
|
+
if (fs33__default.default.existsSync(this.keyPath)) {
|
|
14212
|
+
this.encryptionKey = fs33__default.default.readFileSync(this.keyPath);
|
|
13886
14213
|
} else {
|
|
13887
14214
|
this.encryptionKey = crypto__default.default.randomBytes(32);
|
|
13888
|
-
|
|
14215
|
+
fs33__default.default.writeFileSync(this.keyPath, this.encryptionKey);
|
|
13889
14216
|
}
|
|
13890
14217
|
}
|
|
13891
14218
|
encrypt(text) {
|
|
@@ -13963,9 +14290,9 @@ var init_audit_logger = __esm({
|
|
|
13963
14290
|
dumpDebugIfNeeded() {
|
|
13964
14291
|
if (!this.debugMode) return;
|
|
13965
14292
|
try {
|
|
13966
|
-
const dumpPath =
|
|
14293
|
+
const dumpPath = path36__default.default.join(os10__default.default.tmpdir(), "cascade_audit_logs_debug.json");
|
|
13967
14294
|
const entries = this.getAllLogs();
|
|
13968
|
-
|
|
14295
|
+
fs33__default.default.writeFileSync(dumpPath, JSON.stringify(entries, null, 2), "utf-8");
|
|
13969
14296
|
} catch (err) {
|
|
13970
14297
|
console.error("Failed to dump debug audit logs", err);
|
|
13971
14298
|
}
|
|
@@ -14020,7 +14347,7 @@ var Keystore = class {
|
|
|
14020
14347
|
const creds = await this.keytar.findCredentials(KEYTAR_SERVICE);
|
|
14021
14348
|
this.cache = Object.fromEntries(creds.map((c) => [c.account, c.password]));
|
|
14022
14349
|
this.backend = "keytar";
|
|
14023
|
-
if (password &&
|
|
14350
|
+
if (password && fs33__default.default.existsSync(this.storePath)) {
|
|
14024
14351
|
try {
|
|
14025
14352
|
const fileEntries = this.decryptFile(password);
|
|
14026
14353
|
for (const [k, v] of Object.entries(fileEntries)) {
|
|
@@ -14039,7 +14366,7 @@ var Keystore = class {
|
|
|
14039
14366
|
"Keystore unlock requires a password because the OS keychain (keytar) is not available on this system."
|
|
14040
14367
|
);
|
|
14041
14368
|
}
|
|
14042
|
-
if (!
|
|
14369
|
+
if (!fs33__default.default.existsSync(this.storePath)) {
|
|
14043
14370
|
const salt = crypto__default.default.randomBytes(SALT_LEN);
|
|
14044
14371
|
this.masterKey = this.deriveKey(password, salt);
|
|
14045
14372
|
this.writeWithSalt({}, salt);
|
|
@@ -14053,7 +14380,7 @@ var Keystore = class {
|
|
|
14053
14380
|
}
|
|
14054
14381
|
/** Synchronous legacy unlock kept for AES-only environments. */
|
|
14055
14382
|
unlockSync(password) {
|
|
14056
|
-
if (!
|
|
14383
|
+
if (!fs33__default.default.existsSync(this.storePath)) {
|
|
14057
14384
|
const salt = crypto__default.default.randomBytes(SALT_LEN);
|
|
14058
14385
|
this.masterKey = this.deriveKey(password, salt);
|
|
14059
14386
|
this.writeWithSalt({}, salt);
|
|
@@ -14111,7 +14438,7 @@ var Keystore = class {
|
|
|
14111
14438
|
}
|
|
14112
14439
|
}
|
|
14113
14440
|
decryptFile(password, knownSalt) {
|
|
14114
|
-
if (!
|
|
14441
|
+
if (!fs33__default.default.existsSync(this.storePath)) return {};
|
|
14115
14442
|
try {
|
|
14116
14443
|
const { salt, ciphertext, iv, tag } = this.readRaw();
|
|
14117
14444
|
const useSalt = knownSalt ?? salt;
|
|
@@ -14133,8 +14460,8 @@ var Keystore = class {
|
|
|
14133
14460
|
const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
|
|
14134
14461
|
const tag = cipher.getAuthTag();
|
|
14135
14462
|
const out = Buffer.concat([raw.salt, iv, tag, ciphertext]);
|
|
14136
|
-
|
|
14137
|
-
|
|
14463
|
+
fs33__default.default.mkdirSync(path36__default.default.dirname(this.storePath), { recursive: true });
|
|
14464
|
+
fs33__default.default.writeFileSync(this.storePath, out, { mode: 384 });
|
|
14138
14465
|
}
|
|
14139
14466
|
writeWithSalt(data, salt) {
|
|
14140
14467
|
if (!this.masterKey) throw new Error("writeWithSalt called before masterKey was set");
|
|
@@ -14144,11 +14471,11 @@ var Keystore = class {
|
|
|
14144
14471
|
const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
|
|
14145
14472
|
const tag = cipher.getAuthTag();
|
|
14146
14473
|
const out = Buffer.concat([salt, iv, tag, ciphertext]);
|
|
14147
|
-
|
|
14148
|
-
|
|
14474
|
+
fs33__default.default.mkdirSync(path36__default.default.dirname(this.storePath), { recursive: true });
|
|
14475
|
+
fs33__default.default.writeFileSync(this.storePath, out, { mode: 384 });
|
|
14149
14476
|
}
|
|
14150
14477
|
readRaw() {
|
|
14151
|
-
const buf =
|
|
14478
|
+
const buf = fs33__default.default.readFileSync(this.storePath);
|
|
14152
14479
|
let offset = 0;
|
|
14153
14480
|
const salt = buf.subarray(offset, offset + SALT_LEN);
|
|
14154
14481
|
offset += SALT_LEN;
|
|
@@ -14181,7 +14508,7 @@ var CascadeIgnore = class {
|
|
|
14181
14508
|
]);
|
|
14182
14509
|
}
|
|
14183
14510
|
async load(workspacePath) {
|
|
14184
|
-
const filePath =
|
|
14511
|
+
const filePath = path36__default.default.join(workspacePath, ".cascadeignore");
|
|
14185
14512
|
try {
|
|
14186
14513
|
const content = await fs11__default.default.readFile(filePath, "utf-8");
|
|
14187
14514
|
const lines = content.split("\n").filter((l) => l.trim() && !l.startsWith("#"));
|
|
@@ -14192,7 +14519,7 @@ var CascadeIgnore = class {
|
|
|
14192
14519
|
}
|
|
14193
14520
|
isIgnored(filePath, workspacePath) {
|
|
14194
14521
|
try {
|
|
14195
|
-
const relative = workspacePath ?
|
|
14522
|
+
const relative = workspacePath ? path36__default.default.relative(workspacePath, filePath) : filePath;
|
|
14196
14523
|
return this.ig.ignores(relative);
|
|
14197
14524
|
} catch {
|
|
14198
14525
|
return false;
|
|
@@ -14203,7 +14530,7 @@ var CascadeIgnore = class {
|
|
|
14203
14530
|
}
|
|
14204
14531
|
};
|
|
14205
14532
|
async function createDefaultIgnoreFile(workspacePath) {
|
|
14206
|
-
const filePath =
|
|
14533
|
+
const filePath = path36__default.default.join(workspacePath, ".cascadeignore");
|
|
14207
14534
|
const content = `# .cascadeignore \u2014 Files Cascade agents cannot read or modify
|
|
14208
14535
|
# Syntax identical to .gitignore
|
|
14209
14536
|
|
|
@@ -14233,7 +14560,7 @@ Thumbs.db
|
|
|
14233
14560
|
await fs11__default.default.writeFile(filePath, content, "utf-8");
|
|
14234
14561
|
}
|
|
14235
14562
|
async function loadCascadeMd(workspacePath) {
|
|
14236
|
-
const filePath =
|
|
14563
|
+
const filePath = path36__default.default.join(workspacePath, "CASCADE.md");
|
|
14237
14564
|
try {
|
|
14238
14565
|
const raw = await fs11__default.default.readFile(filePath, "utf-8");
|
|
14239
14566
|
return parseCascadeMd(raw);
|
|
@@ -14262,7 +14589,7 @@ ${raw.trim()}`;
|
|
|
14262
14589
|
return { raw, sections, systemPrompt };
|
|
14263
14590
|
}
|
|
14264
14591
|
async function createDefaultCascadeMd(workspacePath) {
|
|
14265
|
-
const filePath =
|
|
14592
|
+
const filePath = path36__default.default.join(workspacePath, "CASCADE.md");
|
|
14266
14593
|
const content = `# Cascade Project Instructions
|
|
14267
14594
|
|
|
14268
14595
|
This file contains project-specific instructions for the Cascade AI agent.
|
|
@@ -14297,7 +14624,7 @@ List any areas the agent should not touch.
|
|
|
14297
14624
|
var MemoryStore = class _MemoryStore {
|
|
14298
14625
|
db;
|
|
14299
14626
|
constructor(dbPath) {
|
|
14300
|
-
|
|
14627
|
+
fs33__default.default.mkdirSync(path36__default.default.dirname(dbPath), { recursive: true });
|
|
14301
14628
|
try {
|
|
14302
14629
|
this.db = new Database2__default.default(dbPath, { timeout: 5e3 });
|
|
14303
14630
|
this.db.pragma("journal_mode = WAL");
|
|
@@ -15195,7 +15522,18 @@ var WebSearchConfigSchema = zod.z.object({
|
|
|
15195
15522
|
/** Tavily API key — get one at https://tavily.com */
|
|
15196
15523
|
tavilyApiKey: zod.z.string().optional(),
|
|
15197
15524
|
/** Max results per search (default 5) */
|
|
15198
|
-
maxResults: zod.z.number().default(5)
|
|
15525
|
+
maxResults: zod.z.number().default(5),
|
|
15526
|
+
/**
|
|
15527
|
+
* Send `searxngUrl` through the SSRF guard. Off for a local run, where the
|
|
15528
|
+
* URL is the machine owner's own config and a self-hosted SearXNG is
|
|
15529
|
+
* routinely on a private address; on for a host that accepts it from a
|
|
15530
|
+
* request. See `src/tools/web-search.ts`.
|
|
15531
|
+
*
|
|
15532
|
+
* It has to be named HERE, not just on the TypeScript interfaces: the config
|
|
15533
|
+
* passes through `CascadeConfigSchema.parse()` on its way into a run, and
|
|
15534
|
+
* zod drops every key this object does not declare.
|
|
15535
|
+
*/
|
|
15536
|
+
guardSearxngUrl: zod.z.boolean().optional()
|
|
15199
15537
|
});
|
|
15200
15538
|
var ToolsConfigSchema = zod.z.object({
|
|
15201
15539
|
shellAllowlist: zod.z.array(zod.z.string()).default([]),
|
|
@@ -15604,7 +15942,7 @@ function credentialEndpointsConflict(type, rowEndpoint, credentialEndpoint) {
|
|
|
15604
15942
|
|
|
15605
15943
|
// src/config/global-credentials.ts
|
|
15606
15944
|
function credentialsPath(globalDir2) {
|
|
15607
|
-
return
|
|
15945
|
+
return path36__default.default.join(globalDir2, GLOBAL_CREDENTIALS_FILE);
|
|
15608
15946
|
}
|
|
15609
15947
|
function providerKey(p) {
|
|
15610
15948
|
return p.type;
|
|
@@ -15634,7 +15972,7 @@ function isPersistable(p) {
|
|
|
15634
15972
|
}
|
|
15635
15973
|
function loadGlobalCredentials(globalDir2) {
|
|
15636
15974
|
try {
|
|
15637
|
-
const raw =
|
|
15975
|
+
const raw = fs33__default.default.readFileSync(credentialsPath(globalDir2), "utf-8");
|
|
15638
15976
|
const parsed = JSON.parse(raw);
|
|
15639
15977
|
if (!Array.isArray(parsed.providers)) return [];
|
|
15640
15978
|
return parsed.providers.filter(
|
|
@@ -15646,13 +15984,13 @@ function loadGlobalCredentials(globalDir2) {
|
|
|
15646
15984
|
}
|
|
15647
15985
|
function saveGlobalCredentials(globalDir2, providers) {
|
|
15648
15986
|
const filePath = credentialsPath(globalDir2);
|
|
15649
|
-
|
|
15987
|
+
fs33__default.default.mkdirSync(globalDir2, { recursive: true, mode: 448 });
|
|
15650
15988
|
const body = { version: 1, providers: providers.filter(isPersistable) };
|
|
15651
15989
|
const tmp = `${filePath}.tmp`;
|
|
15652
|
-
|
|
15653
|
-
|
|
15990
|
+
fs33__default.default.writeFileSync(tmp, JSON.stringify(body, null, 2), { encoding: "utf-8", mode: 384 });
|
|
15991
|
+
fs33__default.default.renameSync(tmp, filePath);
|
|
15654
15992
|
try {
|
|
15655
|
-
|
|
15993
|
+
fs33__default.default.chmodSync(filePath, 384);
|
|
15656
15994
|
} catch {
|
|
15657
15995
|
}
|
|
15658
15996
|
}
|
|
@@ -16057,7 +16395,7 @@ var ConfigManager = class {
|
|
|
16057
16395
|
/** `globalDirOverride` exists for tests — never point it at the real home dir there. */
|
|
16058
16396
|
constructor(workspacePath = process.cwd(), globalDirOverride) {
|
|
16059
16397
|
this.workspacePath = workspacePath;
|
|
16060
|
-
this.globalDir = globalDirOverride ??
|
|
16398
|
+
this.globalDir = globalDirOverride ?? path36__default.default.join(os10__default.default.homedir(), GLOBAL_CONFIG_DIR);
|
|
16061
16399
|
}
|
|
16062
16400
|
async load() {
|
|
16063
16401
|
this.config = await this.loadConfig();
|
|
@@ -16071,8 +16409,8 @@ var ConfigManager = class {
|
|
|
16071
16409
|
this.ignore = new CascadeIgnore();
|
|
16072
16410
|
await this.ignore.load(this.workspacePath);
|
|
16073
16411
|
this.cascadeMd = await loadCascadeMd(this.workspacePath);
|
|
16074
|
-
this.keystore = new Keystore(
|
|
16075
|
-
this.store = new MemoryStore(
|
|
16412
|
+
this.keystore = new Keystore(path36__default.default.join(this.globalDir, GLOBAL_KEYSTORE_FILE));
|
|
16413
|
+
this.store = new MemoryStore(path36__default.default.join(this.workspacePath, CASCADE_DB_FILE));
|
|
16076
16414
|
const globalRevoked = stripRevokedCredentials(loadGlobalCredentials(this.globalDir));
|
|
16077
16415
|
const globalCreds = filterRetiredCredentials(globalRevoked.kept);
|
|
16078
16416
|
if (globalRevoked.removed > 0) this.revokedCredentials += globalRevoked.removed;
|
|
@@ -16145,8 +16483,8 @@ var ConfigManager = class {
|
|
|
16145
16483
|
* never reached the disk (see `commitSettings`).
|
|
16146
16484
|
*/
|
|
16147
16485
|
async save(config = this.config) {
|
|
16148
|
-
const configPath =
|
|
16149
|
-
await fs11__default.default.mkdir(
|
|
16486
|
+
const configPath = path36__default.default.join(this.workspacePath, CASCADE_CONFIG_FILE);
|
|
16487
|
+
await fs11__default.default.mkdir(path36__default.default.dirname(configPath), { recursive: true });
|
|
16150
16488
|
await fs11__default.default.writeFile(configPath, JSON.stringify(config, null, 2), "utf-8");
|
|
16151
16489
|
try {
|
|
16152
16490
|
saveGlobalCredentials(this.globalDir, config.providers);
|
|
@@ -16196,7 +16534,7 @@ var ConfigManager = class {
|
|
|
16196
16534
|
this.revokedCredentials = 0;
|
|
16197
16535
|
this.revokedPins = [];
|
|
16198
16536
|
this.revokedNotice = void 0;
|
|
16199
|
-
const configPath =
|
|
16537
|
+
const configPath = path36__default.default.join(this.workspacePath, CASCADE_CONFIG_FILE);
|
|
16200
16538
|
try {
|
|
16201
16539
|
const raw = await fs11__default.default.readFile(configPath, "utf-8");
|
|
16202
16540
|
const parsed = JSON.parse(raw);
|
|
@@ -16290,7 +16628,7 @@ var ConfigManager = class {
|
|
|
16290
16628
|
return onResource;
|
|
16291
16629
|
}
|
|
16292
16630
|
async persistClearedPins(tiers) {
|
|
16293
|
-
const configPath =
|
|
16631
|
+
const configPath = path36__default.default.join(this.workspacePath, CASCADE_CONFIG_FILE);
|
|
16294
16632
|
try {
|
|
16295
16633
|
const raw = JSON.parse(await fs11__default.default.readFile(configPath, "utf-8"));
|
|
16296
16634
|
const models = raw["models"];
|
|
@@ -17584,13 +17922,13 @@ var DeadModelStore = class {
|
|
|
17584
17922
|
function fileDeadModelPersistence(filePath) {
|
|
17585
17923
|
return {
|
|
17586
17924
|
load() {
|
|
17587
|
-
if (!
|
|
17588
|
-
const raw = JSON.parse(
|
|
17925
|
+
if (!fs33.existsSync(filePath)) return [];
|
|
17926
|
+
const raw = JSON.parse(fs33.readFileSync(filePath, "utf-8"));
|
|
17589
17927
|
return Array.isArray(raw) ? raw : [];
|
|
17590
17928
|
},
|
|
17591
17929
|
save(records) {
|
|
17592
|
-
|
|
17593
|
-
|
|
17930
|
+
fs33.mkdirSync(path36.dirname(filePath), { recursive: true });
|
|
17931
|
+
fs33.writeFileSync(filePath, JSON.stringify(records, null, 2));
|
|
17594
17932
|
}
|
|
17595
17933
|
};
|
|
17596
17934
|
}
|
|
@@ -18014,7 +18352,7 @@ init_pricing();
|
|
|
18014
18352
|
var DEFAULT_SNAPSHOT_URL = "https://raw.githubusercontent.com/Varun-SV/Cascade-AI/main/src/core/router/benchmark-data.json";
|
|
18015
18353
|
var OPENROUTER_MODELS_URL = "https://openrouter.ai/api/v1/models";
|
|
18016
18354
|
var FETCH_TIMEOUT_MS = 8e3;
|
|
18017
|
-
var DEFAULT_CACHE_FILE =
|
|
18355
|
+
var DEFAULT_CACHE_FILE = path36__default.default.join(os10__default.default.homedir(), GLOBAL_CONFIG_DIR, "benchmarks-cache.json");
|
|
18018
18356
|
function normalizeModelId2(id) {
|
|
18019
18357
|
let s = id.toLowerCase();
|
|
18020
18358
|
const slash = s.lastIndexOf("/");
|
|
@@ -18161,7 +18499,7 @@ var LiveDataProvider = class {
|
|
|
18161
18499
|
}
|
|
18162
18500
|
async saveCache() {
|
|
18163
18501
|
try {
|
|
18164
|
-
await fs11__default.default.mkdir(
|
|
18502
|
+
await fs11__default.default.mkdir(path36__default.default.dirname(this.opts.cacheFile), { recursive: true });
|
|
18165
18503
|
const cache = {
|
|
18166
18504
|
fetchedAt: this.fetchedAt,
|
|
18167
18505
|
snapshot: this.snapshot ?? void 0,
|
|
@@ -18268,9 +18606,15 @@ var FAMILY_BENCHMARKS = {
|
|
|
18268
18606
|
"claude-opus": { code: 95, analysis: 92, creative: 90, data: 88 },
|
|
18269
18607
|
"claude-sonnet": { code: 93, analysis: 88, creative: 87, data: 85 },
|
|
18270
18608
|
"claude-haiku": { code: 80, analysis: 75, creative: 76, data: 72 },
|
|
18271
|
-
// OpenAI GPT-5 family
|
|
18272
|
-
//
|
|
18273
|
-
//
|
|
18609
|
+
// OpenAI GPT-5 family. GPT-5.6 is split by durable capability tier instead
|
|
18610
|
+
// of being folded into generic gpt-5: Sol, Terra and Luna have materially
|
|
18611
|
+
// different benchmark/cost envelopes and should compete independently.
|
|
18612
|
+
// Scores are the committed normalized snapshot; provenance is in
|
|
18613
|
+
// scripts/benchmarks/sources/openai-gpt-5.6-2026-08.json.
|
|
18614
|
+
"gpt-5.6-sol": { code: 100, analysis: 98, creative: 88, data: 88 },
|
|
18615
|
+
"gpt-5.6-terra": { code: 97, analysis: 92, creative: 82, data: 85 },
|
|
18616
|
+
"gpt-5.6-luna": { code: 93, analysis: 85, creative: 74, data: 60 },
|
|
18617
|
+
// Older GPT-5 point releases remain distinct where public data supports it.
|
|
18274
18618
|
"gpt-5.5": { code: 97, analysis: 96, creative: 94, data: 95 },
|
|
18275
18619
|
"gpt-5.4": { code: 94, analysis: 94, creative: 92, data: 92 },
|
|
18276
18620
|
"gpt-5.4-mini": { code: 86, analysis: 85, creative: 85, data: 83 },
|
|
@@ -18306,13 +18650,19 @@ var FAMILY_BENCHMARKS = {
|
|
|
18306
18650
|
"llama-small": { code: 55, analysis: 56, creative: 60, data: 54 }
|
|
18307
18651
|
};
|
|
18308
18652
|
var FAMILY_MATCHERS = [
|
|
18653
|
+
[/fable/i, "claude-opus"],
|
|
18309
18654
|
[/opus/i, "claude-opus"],
|
|
18310
18655
|
[/sonnet/i, "claude-sonnet"],
|
|
18311
18656
|
[/haiku/i, "claude-haiku"],
|
|
18312
|
-
// GPT-5 family — ordered most-specific first.
|
|
18313
|
-
//
|
|
18314
|
-
//
|
|
18657
|
+
// GPT-5 family — ordered most-specific first. GPT-5.6 durable tiers carry
|
|
18658
|
+
// their own profiles. 5.4 Nano intentionally maps to the nano class rather
|
|
18659
|
+
// than being swallowed by the generic 5.4 rule.
|
|
18660
|
+
[/gpt-?5\.6.*sol/i, "gpt-5.6-sol"],
|
|
18661
|
+
[/gpt-?5\.6.*terra/i, "gpt-5.6-terra"],
|
|
18662
|
+
[/gpt-?5\.6.*luna/i, "gpt-5.6-luna"],
|
|
18663
|
+
[/gpt-?5\.6(?:\s|$)/i, "gpt-5.6-sol"],
|
|
18315
18664
|
[/gpt-?5\.5/i, "gpt-5.5"],
|
|
18665
|
+
[/gpt-?5\.4.*nano/i, "gpt-5-nano"],
|
|
18316
18666
|
[/gpt-?5\.4.*mini/i, "gpt-5.4-mini"],
|
|
18317
18667
|
[/gpt-?5\.4/i, "gpt-5.4"],
|
|
18318
18668
|
[/gpt-?5.*nano/i, "gpt-5-nano"],
|
|
@@ -21372,8 +21722,8 @@ HIERARCHY CONTEXT: ${this.hierarchyContext}` : "") + textToolSuffix,
|
|
|
21372
21722
|
// Media generation can run for a minute; without this a cancelled run
|
|
21373
21723
|
// still pays for an image nobody will see.
|
|
21374
21724
|
...this.signal ? { signal: this.signal } : {},
|
|
21375
|
-
saveSnapshot: async (
|
|
21376
|
-
this.store?.addFileSnapshot(this.taskId,
|
|
21725
|
+
saveSnapshot: async (path41, content) => {
|
|
21726
|
+
this.store?.addFileSnapshot(this.taskId, path41, content);
|
|
21377
21727
|
},
|
|
21378
21728
|
sendPeerSync: (to, syncType, content) => {
|
|
21379
21729
|
this.peerBus?.send(this.id, to, syncType, this.assignment?.subtaskId ?? "", content);
|
|
@@ -21576,7 +21926,7 @@ ${assignment.expectedOutput}`;
|
|
|
21576
21926
|
const { promisify: promisify4 } = await import('util');
|
|
21577
21927
|
const execFileAsync2 = promisify4(execFile3);
|
|
21578
21928
|
for (const artifactPath of artifactPaths) {
|
|
21579
|
-
const absolutePath =
|
|
21929
|
+
const absolutePath = path36__default.default.resolve(this.artifactRoot(), artifactPath);
|
|
21580
21930
|
try {
|
|
21581
21931
|
const stat = await fs11__default.default.stat(absolutePath);
|
|
21582
21932
|
if (!stat.isFile()) {
|
|
@@ -21611,7 +21961,7 @@ ${assignment.expectedOutput}`;
|
|
|
21611
21961
|
issues.push(`PDF artifact looks too small to be valid: ${artifactPath}`);
|
|
21612
21962
|
continue;
|
|
21613
21963
|
}
|
|
21614
|
-
const ext =
|
|
21964
|
+
const ext = path36__default.default.extname(absolutePath).toLowerCase();
|
|
21615
21965
|
const check = ext === ".ts" || ext === ".tsx" ? { cmd: "npx", args: ["tsc", "--noEmit", absolutePath] } : ext === ".js" || ext === ".jsx" ? { cmd: process.execPath, args: ["--check", absolutePath] } : ext === ".py" ? { cmd: "python", args: ["-m", "py_compile", absolutePath] } : null;
|
|
21616
21966
|
if (check) {
|
|
21617
21967
|
try {
|
|
@@ -21703,7 +22053,7 @@ HIERARCHY CONTEXT: ${this.hierarchyContext}` : ""),
|
|
|
21703
22053
|
async checkAcceptance(assignment) {
|
|
21704
22054
|
const criteria = assignment.acceptance ?? [];
|
|
21705
22055
|
if (!criteria.length) return [];
|
|
21706
|
-
const resolve2 = (target) =>
|
|
22056
|
+
const resolve2 = (target) => path36__default.default.resolve(this.artifactRoot(), target);
|
|
21707
22057
|
const workerCanWriteFiles = canProduceFiles(this.tools.map((t) => t.name));
|
|
21708
22058
|
return evaluateAcceptance(criteria, assignment.files ?? [], {
|
|
21709
22059
|
stat: async (target) => {
|
|
@@ -25014,16 +25364,16 @@ function resolveInWorkspace(workspaceRoot, input) {
|
|
|
25014
25364
|
if (typeof input !== "string" || input.length === 0) {
|
|
25015
25365
|
throw new WorkspaceSandboxError(String(input), workspaceRoot);
|
|
25016
25366
|
}
|
|
25017
|
-
const root =
|
|
25018
|
-
const abs =
|
|
25019
|
-
const rel =
|
|
25020
|
-
if (rel === "" || rel === ".") ; else if (rel.startsWith("..") ||
|
|
25367
|
+
const root = path36__default.default.resolve(workspaceRoot);
|
|
25368
|
+
const abs = path36__default.default.isAbsolute(input) ? path36__default.default.resolve(input) : path36__default.default.resolve(root, input);
|
|
25369
|
+
const rel = path36__default.default.relative(root, abs);
|
|
25370
|
+
if (rel === "" || rel === ".") ; else if (rel.startsWith("..") || path36__default.default.isAbsolute(rel)) {
|
|
25021
25371
|
throw new WorkspaceSandboxError(input, root);
|
|
25022
25372
|
}
|
|
25023
25373
|
try {
|
|
25024
|
-
const real =
|
|
25025
|
-
const realRel =
|
|
25026
|
-
if (realRel !== "" && realRel !== "." && (realRel.startsWith("..") ||
|
|
25374
|
+
const real = fs33__default.default.realpathSync(abs);
|
|
25375
|
+
const realRel = path36__default.default.relative(root, real);
|
|
25376
|
+
if (realRel !== "" && realRel !== "." && (realRel.startsWith("..") || path36__default.default.isAbsolute(realRel))) {
|
|
25027
25377
|
throw new WorkspaceSandboxError(input, root);
|
|
25028
25378
|
}
|
|
25029
25379
|
} catch (e) {
|
|
@@ -25572,9 +25922,9 @@ async function animatePptx(bytes, scheme) {
|
|
|
25572
25922
|
const zip = await import_jszip.default.loadAsync(bytes);
|
|
25573
25923
|
const slidePaths = Object.keys(zip.files).filter((n) => /^ppt\/slides\/slide\d+\.xml$/.test(n));
|
|
25574
25924
|
if (slidePaths.length === 0) return bytes;
|
|
25575
|
-
for (const
|
|
25576
|
-
const xml = await zip.file(
|
|
25577
|
-
zip.file(
|
|
25925
|
+
for (const path41 of slidePaths) {
|
|
25926
|
+
const xml = await zip.file(path41).async("string");
|
|
25927
|
+
zip.file(path41, animateSlideXml(xml, scheme));
|
|
25578
25928
|
}
|
|
25579
25929
|
return await zip.generateAsync({ type: "uint8array", compression: "DEFLATE" });
|
|
25580
25930
|
} catch {
|
|
@@ -25955,7 +26305,7 @@ var GenerateDocumentTool = class extends BaseTool {
|
|
|
25955
26305
|
}
|
|
25956
26306
|
}
|
|
25957
26307
|
const bytes = await renderDocument(ext, content, { name: filePath, loadImageBytes });
|
|
25958
|
-
await fs11__default.default.mkdir(
|
|
26308
|
+
await fs11__default.default.mkdir(path36__default.default.dirname(absPath), { recursive: true });
|
|
25959
26309
|
await fs11__default.default.writeFile(absPath, bytes);
|
|
25960
26310
|
const charts = countCharts(content);
|
|
25961
26311
|
return [
|
|
@@ -26176,7 +26526,7 @@ var FileWriteTool = class extends BaseTool {
|
|
|
26176
26526
|
} catch {
|
|
26177
26527
|
}
|
|
26178
26528
|
}
|
|
26179
|
-
await fs11__default.default.mkdir(
|
|
26529
|
+
await fs11__default.default.mkdir(path36__default.default.dirname(absPath), { recursive: true });
|
|
26180
26530
|
await fs11__default.default.writeFile(absPath, content, "utf-8");
|
|
26181
26531
|
return `Written ${content.length} characters to ${filePath}`;
|
|
26182
26532
|
}
|
|
@@ -26534,12 +26884,10 @@ ${data.description}`;
|
|
|
26534
26884
|
}
|
|
26535
26885
|
}
|
|
26536
26886
|
};
|
|
26537
|
-
|
|
26538
|
-
// src/tools/browser.ts
|
|
26539
26887
|
var BROWSER_LAUNCH_TIMEOUT_MS = 15e3;
|
|
26540
26888
|
var BrowserTool = class extends BaseTool {
|
|
26541
26889
|
name = "browser";
|
|
26542
|
-
description = "Control a browser: navigate to URLs, click elements, fill forms, take screenshots.
|
|
26890
|
+
description = "Control a browser: navigate to URLs, click elements, fill forms, take screenshots. Screenshots are saved to a file for image_analyze to read.";
|
|
26543
26891
|
inputSchema = {
|
|
26544
26892
|
type: "object",
|
|
26545
26893
|
properties: {
|
|
@@ -26606,7 +26954,14 @@ var BrowserTool = class extends BaseTool {
|
|
|
26606
26954
|
}
|
|
26607
26955
|
case "screenshot": {
|
|
26608
26956
|
const buf = await page2.screenshot({ type: "png" });
|
|
26609
|
-
|
|
26957
|
+
const rel = path36__default.default.join(".cascade", "screenshots", `screenshot-${Date.now()}-${crypto.randomUUID().slice(0, 8)}.png`);
|
|
26958
|
+
const abs = resolveInWorkspace(this.workspaceRoot, rel);
|
|
26959
|
+
await fs11__default.default.mkdir(path36__default.default.dirname(abs), { recursive: true });
|
|
26960
|
+
await fs11__default.default.writeFile(abs, buf);
|
|
26961
|
+
return [
|
|
26962
|
+
`Screenshot saved to ${abs} (${Math.round(buf.byteLength / 1024)} KB).`,
|
|
26963
|
+
`Call image_analyze with that path to see what is on it \u2014 that needs a vision-capable model.`
|
|
26964
|
+
].join(" ");
|
|
26610
26965
|
}
|
|
26611
26966
|
case "evaluate": {
|
|
26612
26967
|
const result = await page2.evaluate(input["script"]);
|
|
@@ -26674,7 +27029,7 @@ var ImageAnalyzeTool = class extends BaseTool {
|
|
|
26674
27029
|
};
|
|
26675
27030
|
async function fileToImageAttachment(filePath) {
|
|
26676
27031
|
const data = await fs11__default.default.readFile(filePath);
|
|
26677
|
-
const ext =
|
|
27032
|
+
const ext = path36__default.default.extname(filePath).toLowerCase();
|
|
26678
27033
|
const mimeMap = {
|
|
26679
27034
|
".jpg": "image/jpeg",
|
|
26680
27035
|
".jpeg": "image/jpeg",
|
|
@@ -26708,14 +27063,14 @@ var PDFCreateTool = class extends BaseTool {
|
|
|
26708
27063
|
const filePath = input["path"];
|
|
26709
27064
|
const content = input["content"];
|
|
26710
27065
|
const title = input["title"];
|
|
26711
|
-
const dir =
|
|
26712
|
-
if (!
|
|
26713
|
-
|
|
27066
|
+
const dir = path36__default.default.dirname(filePath);
|
|
27067
|
+
if (!fs33__default.default.existsSync(dir)) {
|
|
27068
|
+
fs33__default.default.mkdirSync(dir, { recursive: true });
|
|
26714
27069
|
}
|
|
26715
27070
|
return new Promise((resolve2, reject) => {
|
|
26716
27071
|
try {
|
|
26717
27072
|
const doc = new PDFDocument__default.default({ margin: 50 });
|
|
26718
|
-
const stream =
|
|
27073
|
+
const stream = fs33__default.default.createWriteStream(filePath);
|
|
26719
27074
|
doc.pipe(stream);
|
|
26720
27075
|
if (title) {
|
|
26721
27076
|
doc.info["Title"] = title;
|
|
@@ -26793,22 +27148,22 @@ var CodeInterpreterTool = class extends BaseTool {
|
|
|
26793
27148
|
}
|
|
26794
27149
|
cmdPrefix = NODE_CMD;
|
|
26795
27150
|
}
|
|
26796
|
-
const tmpDir =
|
|
26797
|
-
if (!
|
|
26798
|
-
|
|
27151
|
+
const tmpDir = path36__default.default.join(this.workspaceRoot, ".cascade", "tmp");
|
|
27152
|
+
if (!fs33__default.default.existsSync(tmpDir)) {
|
|
27153
|
+
fs33__default.default.mkdirSync(tmpDir, { recursive: true });
|
|
26799
27154
|
}
|
|
26800
27155
|
const extension = language === "python" ? "py" : "js";
|
|
26801
27156
|
const fileName = `intp_${crypto.randomUUID().slice(0, 8)}.${extension}`;
|
|
26802
|
-
const filePath =
|
|
26803
|
-
|
|
27157
|
+
const filePath = path36__default.default.join(tmpDir, fileName);
|
|
27158
|
+
fs33__default.default.writeFileSync(filePath, code, "utf-8");
|
|
26804
27159
|
const execArgs = [filePath, ...args];
|
|
26805
27160
|
return new Promise((resolve2) => {
|
|
26806
27161
|
const startMs = Date.now();
|
|
26807
27162
|
child_process.execFile(cmdPrefix, execArgs, { cwd: this.workspaceRoot, timeout: 3e4 }, (error, stdout, stderr) => {
|
|
26808
27163
|
const duration = Date.now() - startMs;
|
|
26809
27164
|
try {
|
|
26810
|
-
if (
|
|
26811
|
-
|
|
27165
|
+
if (fs33__default.default.existsSync(filePath)) {
|
|
27166
|
+
fs33__default.default.unlinkSync(filePath);
|
|
26812
27167
|
}
|
|
26813
27168
|
} catch (cleanupErr) {
|
|
26814
27169
|
console.error(`Failed to cleanup interpreter script ${filePath}:`, cleanupErr);
|
|
@@ -26888,18 +27243,178 @@ ${formatted}`;
|
|
|
26888
27243
|
return `Unknown action: ${action}`;
|
|
26889
27244
|
}
|
|
26890
27245
|
};
|
|
27246
|
+
var SsrfBlockedError = class extends Error {
|
|
27247
|
+
constructor(message) {
|
|
27248
|
+
super(message);
|
|
27249
|
+
this.name = "SsrfBlockedError";
|
|
27250
|
+
}
|
|
27251
|
+
};
|
|
27252
|
+
var ALLOWED_PROTOCOLS = /* @__PURE__ */ new Set(["http:", "https:"]);
|
|
27253
|
+
var MAX_REDIRECTS2 = 5;
|
|
27254
|
+
function allowLocal() {
|
|
27255
|
+
return process.env["CASCADE_ALLOW_LOCAL_FETCH"] === "1";
|
|
27256
|
+
}
|
|
27257
|
+
function isPrivateAddress(ip) {
|
|
27258
|
+
const type = net__default.default.isIP(ip);
|
|
27259
|
+
if (type === 4) return isPrivateIPv4(ip);
|
|
27260
|
+
if (type === 6) return isPrivateIPv6(ip);
|
|
27261
|
+
return true;
|
|
27262
|
+
}
|
|
27263
|
+
function isPrivateIPv4(ip) {
|
|
27264
|
+
const parts = ip.split(".").map((p) => Number(p));
|
|
27265
|
+
if (parts.length !== 4 || parts.some((p) => Number.isNaN(p) || p < 0 || p > 255)) return true;
|
|
27266
|
+
const [a, b] = parts;
|
|
27267
|
+
if (a === 0) return true;
|
|
27268
|
+
if (a === 10) return true;
|
|
27269
|
+
if (a === 127) return true;
|
|
27270
|
+
if (a === 169 && b === 254) return true;
|
|
27271
|
+
if (a === 172 && b >= 16 && b <= 31) return true;
|
|
27272
|
+
if (a === 192 && b === 168) return true;
|
|
27273
|
+
if (a === 100 && b >= 64 && b <= 127) return true;
|
|
27274
|
+
if (a >= 224) return true;
|
|
27275
|
+
return false;
|
|
27276
|
+
}
|
|
27277
|
+
function ipv6Groups(ip) {
|
|
27278
|
+
let s = ip.toLowerCase().replace(/^\[|\]$/g, "");
|
|
27279
|
+
const zone = s.indexOf("%");
|
|
27280
|
+
if (zone !== -1) s = s.slice(0, zone);
|
|
27281
|
+
const dotted = /^(.*:)(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.exec(s);
|
|
27282
|
+
if (dotted) {
|
|
27283
|
+
const o = [dotted[2], dotted[3], dotted[4], dotted[5]].map((p) => Number(p));
|
|
27284
|
+
if (o.some((n) => !Number.isInteger(n) || n < 0 || n > 255)) return null;
|
|
27285
|
+
s = `${dotted[1]}${(o[0] << 8 | o[1]).toString(16)}:${(o[2] << 8 | o[3]).toString(16)}`;
|
|
27286
|
+
}
|
|
27287
|
+
const halves = s.split("::");
|
|
27288
|
+
if (halves.length > 2) return null;
|
|
27289
|
+
const split = (part) => part ? part.split(":") : [];
|
|
27290
|
+
const head = split(halves[0] ?? "");
|
|
27291
|
+
const tail = halves.length === 2 ? split(halves[1] ?? "") : [];
|
|
27292
|
+
const zeros = halves.length === 2 ? 8 - head.length - tail.length : 0;
|
|
27293
|
+
if (zeros < 0) return null;
|
|
27294
|
+
const groups = [...head, ...Array(zeros).fill("0"), ...tail];
|
|
27295
|
+
if (groups.length !== 8) return null;
|
|
27296
|
+
const out = [];
|
|
27297
|
+
for (const g of groups) {
|
|
27298
|
+
if (!/^[0-9a-f]{1,4}$/.test(g)) return null;
|
|
27299
|
+
out.push(parseInt(g, 16));
|
|
27300
|
+
}
|
|
27301
|
+
return out;
|
|
27302
|
+
}
|
|
27303
|
+
function embeddedIPv4(g) {
|
|
27304
|
+
const quad = (hi, lo) => `${hi >> 8}.${hi & 255}.${lo >> 8}.${lo & 255}`;
|
|
27305
|
+
const leadingZero = (n) => g.slice(0, n).every((x) => x === 0);
|
|
27306
|
+
if (leadingZero(5) && g[5] === 65535) return quad(g[6], g[7]);
|
|
27307
|
+
if (leadingZero(6)) return quad(g[6], g[7]);
|
|
27308
|
+
if (g[0] === 100 && g[1] === 65435) {
|
|
27309
|
+
if (g[2] === 1) {
|
|
27310
|
+
return quad(g[3], (g[4] & 255) << 8 | g[5] >> 8);
|
|
27311
|
+
}
|
|
27312
|
+
if (g[2] === 0 && g[3] === 0 && g[4] === 0 && g[5] === 0) return quad(g[6], g[7]);
|
|
27313
|
+
return null;
|
|
27314
|
+
}
|
|
27315
|
+
if (g[0] === 8194) return quad(g[1], g[2]);
|
|
27316
|
+
return null;
|
|
27317
|
+
}
|
|
27318
|
+
function isPrivateIPv6(ip) {
|
|
27319
|
+
const g = ipv6Groups(ip);
|
|
27320
|
+
if (!g) return true;
|
|
27321
|
+
const v4 = embeddedIPv4(g);
|
|
27322
|
+
if (v4) return isPrivateIPv4(v4);
|
|
27323
|
+
if (g[0] === 100 && g[1] === 65435) return true;
|
|
27324
|
+
if (g.every((x) => x === 0)) return true;
|
|
27325
|
+
if (leading7Zero(g) && g[7] === 1) return true;
|
|
27326
|
+
if ((g[0] & 65472) === 65152) return true;
|
|
27327
|
+
if ((g[0] & 65024) === 64512) return true;
|
|
27328
|
+
if ((g[0] & 65280) === 65280) return true;
|
|
27329
|
+
return false;
|
|
27330
|
+
}
|
|
27331
|
+
function leading7Zero(g) {
|
|
27332
|
+
return g.slice(0, 7).every((x) => x === 0);
|
|
27333
|
+
}
|
|
27334
|
+
async function assertPublicUrl(rawUrl) {
|
|
27335
|
+
let url;
|
|
27336
|
+
try {
|
|
27337
|
+
url = new URL(rawUrl);
|
|
27338
|
+
} catch {
|
|
27339
|
+
throw new SsrfBlockedError(`Invalid URL: ${rawUrl}`);
|
|
27340
|
+
}
|
|
27341
|
+
if (!ALLOWED_PROTOCOLS.has(url.protocol)) {
|
|
27342
|
+
throw new SsrfBlockedError(`Blocked URL scheme "${url.protocol}" \u2014 only http and https are allowed.`);
|
|
27343
|
+
}
|
|
27344
|
+
if (allowLocal()) return url;
|
|
27345
|
+
const host = url.hostname.replace(/^\[|\]$/g, "");
|
|
27346
|
+
if (net__default.default.isIP(host)) {
|
|
27347
|
+
if (isPrivateAddress(host)) {
|
|
27348
|
+
throw new SsrfBlockedError(`Blocked request to non-public address ${host}.`);
|
|
27349
|
+
}
|
|
27350
|
+
return url;
|
|
27351
|
+
}
|
|
27352
|
+
if (host === "localhost" || host.endsWith(".localhost") || host.endsWith(".local")) {
|
|
27353
|
+
throw new SsrfBlockedError(`Blocked request to local hostname "${host}".`);
|
|
27354
|
+
}
|
|
27355
|
+
let addresses;
|
|
27356
|
+
try {
|
|
27357
|
+
const records = await dns2__default.default.lookup(host, { all: true });
|
|
27358
|
+
addresses = records.map((r) => r.address);
|
|
27359
|
+
} catch {
|
|
27360
|
+
throw new SsrfBlockedError(`Could not resolve host "${host}".`);
|
|
27361
|
+
}
|
|
27362
|
+
if (addresses.length === 0 || addresses.some((addr) => isPrivateAddress(addr))) {
|
|
27363
|
+
throw new SsrfBlockedError(`Blocked request to "${host}" \u2014 resolves to a non-public address.`);
|
|
27364
|
+
}
|
|
27365
|
+
return url;
|
|
27366
|
+
}
|
|
27367
|
+
var ssrfAgent = new undici.Agent({
|
|
27368
|
+
connect: {
|
|
27369
|
+
lookup(hostname, options, callback) {
|
|
27370
|
+
if (allowLocal()) {
|
|
27371
|
+
dnsCallback__default.default.lookup(hostname, options, callback);
|
|
27372
|
+
return;
|
|
27373
|
+
}
|
|
27374
|
+
dnsCallback__default.default.lookup(hostname, { ...options, all: true }, (err, addresses) => {
|
|
27375
|
+
if (err) return callback(err, "", 0);
|
|
27376
|
+
const list = Array.isArray(addresses) ? addresses : [addresses];
|
|
27377
|
+
const bad = list.find((a) => isPrivateAddress(a.address));
|
|
27378
|
+
if (bad) {
|
|
27379
|
+
return callback(
|
|
27380
|
+
new SsrfBlockedError(`Blocked connection to "${hostname}" \u2014 resolved to non-public address ${bad.address}.`),
|
|
27381
|
+
"",
|
|
27382
|
+
0
|
|
27383
|
+
);
|
|
27384
|
+
}
|
|
27385
|
+
if (options.all) return callback(null, list);
|
|
27386
|
+
const first = list[0];
|
|
27387
|
+
return callback(null, first.address, first.family);
|
|
27388
|
+
});
|
|
27389
|
+
}
|
|
27390
|
+
}
|
|
27391
|
+
});
|
|
27392
|
+
async function safeFetch(rawUrl, init = {}) {
|
|
27393
|
+
let currentUrl = (await assertPublicUrl(rawUrl)).toString();
|
|
27394
|
+
for (let i = 0; i <= MAX_REDIRECTS2; i++) {
|
|
27395
|
+
const resp = await fetch(currentUrl, { ...init, redirect: "manual", dispatcher: ssrfAgent });
|
|
27396
|
+
if (resp.status < 300 || resp.status >= 400) return resp;
|
|
27397
|
+
const location = resp.headers.get("location");
|
|
27398
|
+
if (!location) return resp;
|
|
27399
|
+
const next = new URL(location, currentUrl);
|
|
27400
|
+
await assertPublicUrl(next.toString());
|
|
27401
|
+
currentUrl = next.toString();
|
|
27402
|
+
}
|
|
27403
|
+
throw new SsrfBlockedError(`Too many redirects (>${MAX_REDIRECTS2}).`);
|
|
27404
|
+
}
|
|
26891
27405
|
|
|
26892
27406
|
// src/tools/web-search.ts
|
|
26893
|
-
async function searchSearXNG(query, baseUrl, maxResults) {
|
|
27407
|
+
async function searchSearXNG(query, baseUrl, maxResults, guardUrl = false) {
|
|
26894
27408
|
const url = new URL("/search", baseUrl);
|
|
26895
27409
|
url.searchParams.set("q", query);
|
|
26896
27410
|
url.searchParams.set("format", "json");
|
|
26897
27411
|
url.searchParams.set("categories", "general");
|
|
26898
27412
|
url.searchParams.set("engines", "google,bing,duckduckgo");
|
|
26899
|
-
const
|
|
27413
|
+
const init = {
|
|
26900
27414
|
headers: { "User-Agent": "Cascade-AI/1.0 WebSearchTool" },
|
|
26901
27415
|
signal: AbortSignal.timeout(1e4)
|
|
26902
|
-
}
|
|
27416
|
+
};
|
|
27417
|
+
const resp = guardUrl ? await safeFetch(url.toString(), init) : await fetch(url.toString(), init);
|
|
26903
27418
|
if (!resp.ok) {
|
|
26904
27419
|
throw new Error(`SearXNG returned HTTP ${resp.status}`);
|
|
26905
27420
|
}
|
|
@@ -27028,7 +27543,11 @@ var WebSearchTool = class extends BaseTool {
|
|
|
27028
27543
|
searxngUrl: config.searxngUrl ?? process.env["SEARXNG_URL"],
|
|
27029
27544
|
braveApiKey: config.braveApiKey ?? process.env["BRAVE_SEARCH_API_KEY"],
|
|
27030
27545
|
tavilyApiKey: config.tavilyApiKey ?? process.env["TAVILY_API_KEY"],
|
|
27031
|
-
maxResults: config.maxResults ?? 5
|
|
27546
|
+
maxResults: config.maxResults ?? 5,
|
|
27547
|
+
// Note this reads only from `config`, never from the environment: the
|
|
27548
|
+
// guard tracks the trustworthiness of the URL the host passed in, and an
|
|
27549
|
+
// env var says nothing about that.
|
|
27550
|
+
guardSearxngUrl: config.guardSearxngUrl ?? false
|
|
27032
27551
|
};
|
|
27033
27552
|
}
|
|
27034
27553
|
async execute(input, _options) {
|
|
@@ -27043,7 +27562,7 @@ var WebSearchTool = class extends BaseTool {
|
|
|
27043
27562
|
let anyBackendReachable = false;
|
|
27044
27563
|
if (this.config.searxngUrl) {
|
|
27045
27564
|
try {
|
|
27046
|
-
results = await searchSearXNG(query, this.config.searxngUrl, maxResults);
|
|
27565
|
+
results = await searchSearXNG(query, this.config.searxngUrl, maxResults, this.config.guardSearxngUrl);
|
|
27047
27566
|
anyBackendReachable = true;
|
|
27048
27567
|
if (results.length > 0) return this.formatResults(query, results);
|
|
27049
27568
|
errors.push("SearXNG: returned 0 results");
|
|
@@ -27120,7 +27639,7 @@ var GlobTool = class extends BaseTool {
|
|
|
27120
27639
|
};
|
|
27121
27640
|
async execute(input, _options) {
|
|
27122
27641
|
const pattern = input["pattern"];
|
|
27123
|
-
const searchPath = input["path"] ?
|
|
27642
|
+
const searchPath = input["path"] ? path36__default.default.resolve(this.workspaceRoot, input["path"]) : this.workspaceRoot;
|
|
27124
27643
|
const matches = await glob.glob(pattern, {
|
|
27125
27644
|
cwd: searchPath,
|
|
27126
27645
|
ignore: ["node_modules/**", ".git/**", "dist/**", "build/**"],
|
|
@@ -27133,7 +27652,7 @@ var GlobTool = class extends BaseTool {
|
|
|
27133
27652
|
const withMtime = await Promise.all(
|
|
27134
27653
|
matches.map(async (rel) => {
|
|
27135
27654
|
try {
|
|
27136
|
-
const stat = await fs11__default.default.stat(
|
|
27655
|
+
const stat = await fs11__default.default.stat(path36__default.default.join(searchPath, rel));
|
|
27137
27656
|
return { rel, mtime: stat.mtimeMs };
|
|
27138
27657
|
} catch {
|
|
27139
27658
|
return { rel, mtime: 0 };
|
|
@@ -27182,7 +27701,7 @@ var GrepTool = class extends BaseTool {
|
|
|
27182
27701
|
};
|
|
27183
27702
|
async execute(input, _options) {
|
|
27184
27703
|
const pattern = input["pattern"];
|
|
27185
|
-
const searchPath = input["path"] ?
|
|
27704
|
+
const searchPath = input["path"] ? path36__default.default.resolve(this.workspaceRoot, input["path"]) : this.workspaceRoot;
|
|
27186
27705
|
const globPattern = input["glob"];
|
|
27187
27706
|
const outputMode = input["output_mode"] ?? "content";
|
|
27188
27707
|
const context = input["context"] ?? 0;
|
|
@@ -27236,12 +27755,12 @@ var GrepTool = class extends BaseTool {
|
|
|
27236
27755
|
nodir: true
|
|
27237
27756
|
});
|
|
27238
27757
|
} catch {
|
|
27239
|
-
files = [
|
|
27758
|
+
files = [path36__default.default.relative(searchPath, searchPath) || "."];
|
|
27240
27759
|
}
|
|
27241
27760
|
const results = [];
|
|
27242
27761
|
let totalCount = 0;
|
|
27243
27762
|
for (const rel of files) {
|
|
27244
|
-
const abs =
|
|
27763
|
+
const abs = path36__default.default.join(searchPath, rel);
|
|
27245
27764
|
let content;
|
|
27246
27765
|
try {
|
|
27247
27766
|
content = await fs11__default.default.readFile(abs, "utf-8");
|
|
@@ -27282,92 +27801,6 @@ Total: ${totalCount} matches`);
|
|
|
27282
27801
|
return results.join("\n");
|
|
27283
27802
|
}
|
|
27284
27803
|
};
|
|
27285
|
-
var SsrfBlockedError = class extends Error {
|
|
27286
|
-
constructor(message) {
|
|
27287
|
-
super(message);
|
|
27288
|
-
this.name = "SsrfBlockedError";
|
|
27289
|
-
}
|
|
27290
|
-
};
|
|
27291
|
-
var ALLOWED_PROTOCOLS = /* @__PURE__ */ new Set(["http:", "https:"]);
|
|
27292
|
-
var MAX_REDIRECTS2 = 5;
|
|
27293
|
-
function allowLocal() {
|
|
27294
|
-
return process.env["CASCADE_ALLOW_LOCAL_FETCH"] === "1";
|
|
27295
|
-
}
|
|
27296
|
-
function isPrivateAddress(ip) {
|
|
27297
|
-
const type = net__default.default.isIP(ip);
|
|
27298
|
-
if (type === 4) return isPrivateIPv4(ip);
|
|
27299
|
-
if (type === 6) return isPrivateIPv6(ip);
|
|
27300
|
-
return true;
|
|
27301
|
-
}
|
|
27302
|
-
function isPrivateIPv4(ip) {
|
|
27303
|
-
const parts = ip.split(".").map((p) => Number(p));
|
|
27304
|
-
if (parts.length !== 4 || parts.some((p) => Number.isNaN(p) || p < 0 || p > 255)) return true;
|
|
27305
|
-
const [a, b] = parts;
|
|
27306
|
-
if (a === 0) return true;
|
|
27307
|
-
if (a === 10) return true;
|
|
27308
|
-
if (a === 127) return true;
|
|
27309
|
-
if (a === 169 && b === 254) return true;
|
|
27310
|
-
if (a === 172 && b >= 16 && b <= 31) return true;
|
|
27311
|
-
if (a === 192 && b === 168) return true;
|
|
27312
|
-
if (a === 100 && b >= 64 && b <= 127) return true;
|
|
27313
|
-
if (a >= 224) return true;
|
|
27314
|
-
return false;
|
|
27315
|
-
}
|
|
27316
|
-
function isPrivateIPv6(ip) {
|
|
27317
|
-
const lower = ip.toLowerCase().replace(/^\[|\]$/g, "");
|
|
27318
|
-
if (lower === "::1" || lower === "::") return true;
|
|
27319
|
-
if (lower.startsWith("fe80")) return true;
|
|
27320
|
-
if (lower.startsWith("fc") || lower.startsWith("fd")) return true;
|
|
27321
|
-
const mapped = /^::ffff:(\d+\.\d+\.\d+\.\d+)$/.exec(lower);
|
|
27322
|
-
if (mapped) return isPrivateIPv4(mapped[1]);
|
|
27323
|
-
return false;
|
|
27324
|
-
}
|
|
27325
|
-
async function assertPublicUrl(rawUrl) {
|
|
27326
|
-
let url;
|
|
27327
|
-
try {
|
|
27328
|
-
url = new URL(rawUrl);
|
|
27329
|
-
} catch {
|
|
27330
|
-
throw new SsrfBlockedError(`Invalid URL: ${rawUrl}`);
|
|
27331
|
-
}
|
|
27332
|
-
if (!ALLOWED_PROTOCOLS.has(url.protocol)) {
|
|
27333
|
-
throw new SsrfBlockedError(`Blocked URL scheme "${url.protocol}" \u2014 only http and https are allowed.`);
|
|
27334
|
-
}
|
|
27335
|
-
if (allowLocal()) return url;
|
|
27336
|
-
const host = url.hostname.replace(/^\[|\]$/g, "");
|
|
27337
|
-
if (net__default.default.isIP(host)) {
|
|
27338
|
-
if (isPrivateAddress(host)) {
|
|
27339
|
-
throw new SsrfBlockedError(`Blocked request to non-public address ${host}.`);
|
|
27340
|
-
}
|
|
27341
|
-
return url;
|
|
27342
|
-
}
|
|
27343
|
-
if (host === "localhost" || host.endsWith(".localhost") || host.endsWith(".local")) {
|
|
27344
|
-
throw new SsrfBlockedError(`Blocked request to local hostname "${host}".`);
|
|
27345
|
-
}
|
|
27346
|
-
let addresses;
|
|
27347
|
-
try {
|
|
27348
|
-
const records = await dns2__default.default.lookup(host, { all: true });
|
|
27349
|
-
addresses = records.map((r) => r.address);
|
|
27350
|
-
} catch {
|
|
27351
|
-
throw new SsrfBlockedError(`Could not resolve host "${host}".`);
|
|
27352
|
-
}
|
|
27353
|
-
if (addresses.length === 0 || addresses.some((addr) => isPrivateAddress(addr))) {
|
|
27354
|
-
throw new SsrfBlockedError(`Blocked request to "${host}" \u2014 resolves to a non-public address.`);
|
|
27355
|
-
}
|
|
27356
|
-
return url;
|
|
27357
|
-
}
|
|
27358
|
-
async function safeFetch(rawUrl, init = {}) {
|
|
27359
|
-
let currentUrl = (await assertPublicUrl(rawUrl)).toString();
|
|
27360
|
-
for (let i = 0; i <= MAX_REDIRECTS2; i++) {
|
|
27361
|
-
const resp = await fetch(currentUrl, { ...init, redirect: "manual" });
|
|
27362
|
-
if (resp.status < 300 || resp.status >= 400) return resp;
|
|
27363
|
-
const location = resp.headers.get("location");
|
|
27364
|
-
if (!location) return resp;
|
|
27365
|
-
const next = new URL(location, currentUrl);
|
|
27366
|
-
await assertPublicUrl(next.toString());
|
|
27367
|
-
currentUrl = next.toString();
|
|
27368
|
-
}
|
|
27369
|
-
throw new SsrfBlockedError(`Too many redirects (>${MAX_REDIRECTS2}).`);
|
|
27370
|
-
}
|
|
27371
27804
|
|
|
27372
27805
|
// src/tools/web-fetch.ts
|
|
27373
27806
|
var MAX_CHARS = 5e4;
|
|
@@ -27640,10 +28073,10 @@ var ToolRegistry = class extends EventEmitter__default.default {
|
|
|
27640
28073
|
}
|
|
27641
28074
|
isIgnored(filePath) {
|
|
27642
28075
|
if (!filePath) return false;
|
|
27643
|
-
const abs =
|
|
27644
|
-
const rel =
|
|
27645
|
-
if (!rel || rel.startsWith("..") ||
|
|
27646
|
-
const posixRel = rel.split(
|
|
28076
|
+
const abs = path36__default.default.resolve(this.workspaceRoot, filePath);
|
|
28077
|
+
const rel = path36__default.default.relative(this.workspaceRoot, abs);
|
|
28078
|
+
if (!rel || rel.startsWith("..") || path36__default.default.isAbsolute(rel)) return true;
|
|
28079
|
+
const posixRel = rel.split(path36__default.default.sep).join("/");
|
|
27647
28080
|
return this.ignoreMatcher.ignores(posixRel);
|
|
27648
28081
|
}
|
|
27649
28082
|
};
|
|
@@ -27877,22 +28310,22 @@ var FileMcpOAuthStore = class {
|
|
|
27877
28310
|
filePath;
|
|
27878
28311
|
load() {
|
|
27879
28312
|
try {
|
|
27880
|
-
return JSON.parse(
|
|
28313
|
+
return JSON.parse(fs33__default.default.readFileSync(this.filePath, "utf-8"));
|
|
27881
28314
|
} catch {
|
|
27882
28315
|
return void 0;
|
|
27883
28316
|
}
|
|
27884
28317
|
}
|
|
27885
28318
|
save(state) {
|
|
27886
|
-
|
|
27887
|
-
|
|
28319
|
+
fs33__default.default.mkdirSync(path36__default.default.dirname(this.filePath), { recursive: true, mode: 448 });
|
|
28320
|
+
fs33__default.default.writeFileSync(this.filePath, JSON.stringify(state, null, 2), { mode: 384 });
|
|
27888
28321
|
try {
|
|
27889
|
-
|
|
28322
|
+
fs33__default.default.chmodSync(this.filePath, 384);
|
|
27890
28323
|
} catch {
|
|
27891
28324
|
}
|
|
27892
28325
|
}
|
|
27893
28326
|
clear() {
|
|
27894
28327
|
try {
|
|
27895
|
-
|
|
28328
|
+
fs33__default.default.rmSync(this.filePath);
|
|
27896
28329
|
} catch {
|
|
27897
28330
|
}
|
|
27898
28331
|
}
|
|
@@ -28712,7 +29145,7 @@ var TaskAnalyzer = class {
|
|
|
28712
29145
|
|
|
28713
29146
|
// src/core/router/model-performance-tracker.ts
|
|
28714
29147
|
init_pricing();
|
|
28715
|
-
var DEFAULT_STATS_FILE =
|
|
29148
|
+
var DEFAULT_STATS_FILE = path36__default.default.join(os10__default.default.homedir(), ".cascade", "model-perf.json");
|
|
28716
29149
|
var ModelPerformanceTracker = class _ModelPerformanceTracker {
|
|
28717
29150
|
stats = /* @__PURE__ */ new Map();
|
|
28718
29151
|
featureStats = /* @__PURE__ */ new Map();
|
|
@@ -28752,7 +29185,7 @@ var ModelPerformanceTracker = class _ModelPerformanceTracker {
|
|
|
28752
29185
|
async save() {
|
|
28753
29186
|
if (this.readOnly) return;
|
|
28754
29187
|
try {
|
|
28755
|
-
await fs11__default.default.mkdir(
|
|
29188
|
+
await fs11__default.default.mkdir(path36__default.default.dirname(this.statsFile), { recursive: true });
|
|
28756
29189
|
const modelsObj = {};
|
|
28757
29190
|
const featuresObj = {};
|
|
28758
29191
|
for (const [key, stat] of this.stats) modelsObj[key] = stat;
|
|
@@ -29385,7 +29818,7 @@ Required capability: ${description.slice(0, 300)}`;
|
|
|
29385
29818
|
* any dangerous action, so a silently-reloaded tool can't act without approval. */
|
|
29386
29819
|
async loadPersistedTools() {
|
|
29387
29820
|
if (!this.workspacePath || !this.persistEnabled) return;
|
|
29388
|
-
const file =
|
|
29821
|
+
const file = path36__default.default.join(this.workspacePath, ".cascade", DYNAMIC_TOOLS_FILE);
|
|
29389
29822
|
try {
|
|
29390
29823
|
const raw = await fs11__default.default.readFile(file, "utf-8");
|
|
29391
29824
|
const specs = JSON.parse(raw);
|
|
@@ -29409,8 +29842,8 @@ Required capability: ${description.slice(0, 300)}`;
|
|
|
29409
29842
|
}
|
|
29410
29843
|
async persist() {
|
|
29411
29844
|
if (!this.workspacePath || !this.persistEnabled) return;
|
|
29412
|
-
const dir =
|
|
29413
|
-
const file =
|
|
29845
|
+
const dir = path36__default.default.join(this.workspacePath, ".cascade");
|
|
29846
|
+
const file = path36__default.default.join(dir, DYNAMIC_TOOLS_FILE);
|
|
29414
29847
|
try {
|
|
29415
29848
|
await fs11__default.default.mkdir(dir, { recursive: true });
|
|
29416
29849
|
await fs11__default.default.writeFile(file, JSON.stringify(Array.from(this.specs.values()), null, 2), "utf-8");
|
|
@@ -29430,12 +29863,12 @@ var WorldStateDB = class {
|
|
|
29430
29863
|
constructor(workspacePath, debugMode = false) {
|
|
29431
29864
|
this.workspacePath = workspacePath;
|
|
29432
29865
|
this.debugMode = debugMode;
|
|
29433
|
-
const cascadeDir =
|
|
29434
|
-
if (!
|
|
29435
|
-
|
|
29866
|
+
const cascadeDir = path36__default.default.join(workspacePath, ".cascade");
|
|
29867
|
+
if (!fs33__default.default.existsSync(cascadeDir)) {
|
|
29868
|
+
fs33__default.default.mkdirSync(cascadeDir, { recursive: true });
|
|
29436
29869
|
}
|
|
29437
|
-
this.keyPath =
|
|
29438
|
-
this.dbPath =
|
|
29870
|
+
this.keyPath = path36__default.default.join(cascadeDir, "world_state.key");
|
|
29871
|
+
this.dbPath = path36__default.default.join(cascadeDir, "world_state.db");
|
|
29439
29872
|
this.initEncryptionKey();
|
|
29440
29873
|
this.db = new Database2__default.default(this.dbPath);
|
|
29441
29874
|
this.db.pragma("journal_mode = WAL");
|
|
@@ -29492,11 +29925,11 @@ var WorldStateDB = class {
|
|
|
29492
29925
|
).run(e, r, row.encrypted_value, row.source_worker, row.timestamp, validTo, change);
|
|
29493
29926
|
}
|
|
29494
29927
|
initEncryptionKey() {
|
|
29495
|
-
if (
|
|
29496
|
-
this.encryptionKey =
|
|
29928
|
+
if (fs33__default.default.existsSync(this.keyPath)) {
|
|
29929
|
+
this.encryptionKey = fs33__default.default.readFileSync(this.keyPath);
|
|
29497
29930
|
} else {
|
|
29498
29931
|
this.encryptionKey = crypto__default.default.randomBytes(32);
|
|
29499
|
-
|
|
29932
|
+
fs33__default.default.writeFileSync(this.keyPath, this.encryptionKey);
|
|
29500
29933
|
}
|
|
29501
29934
|
}
|
|
29502
29935
|
encrypt(text) {
|
|
@@ -29782,9 +30215,9 @@ var WorldStateDB = class {
|
|
|
29782
30215
|
dumpDebugIfNeeded() {
|
|
29783
30216
|
if (!this.debugMode) return;
|
|
29784
30217
|
try {
|
|
29785
|
-
const dumpPath =
|
|
30218
|
+
const dumpPath = path36__default.default.join(os10__default.default.tmpdir(), "cascade_world_state_debug.json");
|
|
29786
30219
|
const entries = this.getAllEntries();
|
|
29787
|
-
|
|
30220
|
+
fs33__default.default.writeFileSync(dumpPath, JSON.stringify(entries, null, 2), "utf-8");
|
|
29788
30221
|
} catch (err) {
|
|
29789
30222
|
console.error("Failed to dump debug world state", err);
|
|
29790
30223
|
}
|
|
@@ -29840,11 +30273,11 @@ var ResumeStore = class {
|
|
|
29840
30273
|
version: RESUME_SCHEMA_VERSION,
|
|
29841
30274
|
createdAt: checkpoint.createdAt ?? new Date(timestamp).toISOString()
|
|
29842
30275
|
};
|
|
29843
|
-
await
|
|
29844
|
-
const finalPath =
|
|
30276
|
+
await fs33.promises.mkdir(this.dir, { recursive: true });
|
|
30277
|
+
const finalPath = path36__default.default.join(this.dir, `${timestamp}-${safeId(record.taskId)}.json`);
|
|
29845
30278
|
const tempPath = `${finalPath}.${process.pid}.tmp`;
|
|
29846
|
-
await
|
|
29847
|
-
await
|
|
30279
|
+
await fs33.promises.writeFile(tempPath, JSON.stringify(record, null, 2), "utf-8");
|
|
30280
|
+
await fs33.promises.rename(tempPath, finalPath);
|
|
29848
30281
|
await this.prune();
|
|
29849
30282
|
return true;
|
|
29850
30283
|
} catch {
|
|
@@ -29855,7 +30288,7 @@ var ResumeStore = class {
|
|
|
29855
30288
|
async list() {
|
|
29856
30289
|
let entries;
|
|
29857
30290
|
try {
|
|
29858
|
-
entries = await
|
|
30291
|
+
entries = await fs33.promises.readdir(this.dir);
|
|
29859
30292
|
} catch {
|
|
29860
30293
|
return [];
|
|
29861
30294
|
}
|
|
@@ -29864,7 +30297,7 @@ var ResumeStore = class {
|
|
|
29864
30297
|
const checkpoints = [];
|
|
29865
30298
|
for (const candidate of candidates2) {
|
|
29866
30299
|
try {
|
|
29867
|
-
const raw = await
|
|
30300
|
+
const raw = await fs33.promises.readFile(path36__default.default.join(this.dir, candidate.name), "utf-8");
|
|
29868
30301
|
const parsed = JSON.parse(raw);
|
|
29869
30302
|
if (isCheckpoint(parsed)) checkpoints.push(parsed);
|
|
29870
30303
|
} catch {
|
|
@@ -29898,12 +30331,12 @@ var ResumeStore = class {
|
|
|
29898
30331
|
const target = taskId ? all.find((c) => c.taskId === taskId) : all[0];
|
|
29899
30332
|
if (!target) return null;
|
|
29900
30333
|
try {
|
|
29901
|
-
const entries = await
|
|
30334
|
+
const entries = await fs33.promises.readdir(this.dir);
|
|
29902
30335
|
const wanted = safeId(target.taskId);
|
|
29903
30336
|
const source = entries.find((name) => FILE_PATTERN.exec(name)?.[2] === wanted);
|
|
29904
30337
|
if (!source) return null;
|
|
29905
30338
|
const claimId = `${this.now()}-${safeId(target.taskId)}`;
|
|
29906
|
-
await
|
|
30339
|
+
await fs33.promises.rename(path36__default.default.join(this.dir, source), path36__default.default.join(this.dir, `${claimId}${CLAIM_SUFFIX}`));
|
|
29907
30340
|
return { checkpoint: target, claimId };
|
|
29908
30341
|
} catch {
|
|
29909
30342
|
return null;
|
|
@@ -29912,9 +30345,9 @@ var ResumeStore = class {
|
|
|
29912
30345
|
/** Give a claim back, so the work stays recoverable after a failed start. */
|
|
29913
30346
|
async release(claimId) {
|
|
29914
30347
|
try {
|
|
29915
|
-
await
|
|
29916
|
-
|
|
29917
|
-
|
|
30348
|
+
await fs33.promises.rename(
|
|
30349
|
+
path36__default.default.join(this.dir, `${claimId}${CLAIM_SUFFIX}`),
|
|
30350
|
+
path36__default.default.join(this.dir, `${claimId}.json`)
|
|
29918
30351
|
);
|
|
29919
30352
|
} catch {
|
|
29920
30353
|
}
|
|
@@ -29922,7 +30355,7 @@ var ResumeStore = class {
|
|
|
29922
30355
|
/** Discard a claim for good — the resumed run has taken ownership. */
|
|
29923
30356
|
async settle(claimId) {
|
|
29924
30357
|
try {
|
|
29925
|
-
await
|
|
30358
|
+
await fs33.promises.rm(path36__default.default.join(this.dir, `${claimId}${CLAIM_SUFFIX}`), { force: true });
|
|
29926
30359
|
} catch {
|
|
29927
30360
|
}
|
|
29928
30361
|
}
|
|
@@ -29944,15 +30377,15 @@ var ResumeStore = class {
|
|
|
29944
30377
|
async reclaimStale() {
|
|
29945
30378
|
let reclaimed = 0;
|
|
29946
30379
|
try {
|
|
29947
|
-
const entries = await
|
|
30380
|
+
const entries = await fs33.promises.readdir(this.dir);
|
|
29948
30381
|
const cutoff = this.now() - this.claimTimeoutMs;
|
|
29949
30382
|
for (const name of entries) {
|
|
29950
30383
|
if (!name.endsWith(CLAIM_SUFFIX)) continue;
|
|
29951
30384
|
const stamp2 = Number(/^(\d+)-/.exec(name)?.[1]);
|
|
29952
30385
|
if (!Number.isFinite(stamp2) || stamp2 >= cutoff) continue;
|
|
29953
|
-
await
|
|
29954
|
-
|
|
29955
|
-
|
|
30386
|
+
await fs33.promises.rename(
|
|
30387
|
+
path36__default.default.join(this.dir, name),
|
|
30388
|
+
path36__default.default.join(this.dir, `${name.slice(0, -CLAIM_SUFFIX.length)}.json`)
|
|
29956
30389
|
);
|
|
29957
30390
|
reclaimed++;
|
|
29958
30391
|
}
|
|
@@ -29963,12 +30396,12 @@ var ResumeStore = class {
|
|
|
29963
30396
|
/** Remove every checkpoint for a task id. */
|
|
29964
30397
|
async delete(taskId) {
|
|
29965
30398
|
try {
|
|
29966
|
-
const entries = await
|
|
30399
|
+
const entries = await fs33.promises.readdir(this.dir);
|
|
29967
30400
|
const wanted = safeId(taskId);
|
|
29968
30401
|
await Promise.all(entries.map(async (name) => {
|
|
29969
30402
|
const match = FILE_PATTERN.exec(name);
|
|
29970
30403
|
if (match?.[2] === wanted) {
|
|
29971
|
-
await
|
|
30404
|
+
await fs33.promises.rm(path36__default.default.join(this.dir, name), { force: true });
|
|
29972
30405
|
}
|
|
29973
30406
|
}));
|
|
29974
30407
|
} catch {
|
|
@@ -29977,13 +30410,13 @@ var ResumeStore = class {
|
|
|
29977
30410
|
/** Drop expired checkpoints, then any beyond the newest `maxCheckpoints`. */
|
|
29978
30411
|
async prune() {
|
|
29979
30412
|
try {
|
|
29980
|
-
const entries = await
|
|
30413
|
+
const entries = await fs33.promises.readdir(this.dir);
|
|
29981
30414
|
const cutoff = this.now() - this.maxAgeMs;
|
|
29982
30415
|
const files = entries.map((name) => ({ name, match: FILE_PATTERN.exec(name) })).filter((e) => e.match !== null).map((e) => ({ name: e.name, timestamp: Number(e.match[1]) })).sort((a, b) => b.timestamp - a.timestamp);
|
|
29983
30416
|
const doomed = files.filter((f, index) => f.timestamp < cutoff || index >= this.maxCheckpoints);
|
|
29984
30417
|
const staleTemps = entries.filter((name) => name.endsWith(".tmp")).filter((name) => (Number(FILE_PATTERN.exec(name.replace(/\.\d+\.tmp$/, ".json"))?.[1]) || 0) < cutoff);
|
|
29985
30418
|
await Promise.all([...doomed.map((f) => f.name), ...staleTemps].map(
|
|
29986
|
-
(name) =>
|
|
30419
|
+
(name) => fs33.promises.rm(path36__default.default.join(this.dir, name), { force: true })
|
|
29987
30420
|
));
|
|
29988
30421
|
} catch {
|
|
29989
30422
|
}
|
|
@@ -30360,7 +30793,7 @@ var WorkspaceIndex = class {
|
|
|
30360
30793
|
isIgnored;
|
|
30361
30794
|
chunker;
|
|
30362
30795
|
constructor(opts) {
|
|
30363
|
-
this.root =
|
|
30796
|
+
this.root = path36__default.default.resolve(opts.root);
|
|
30364
30797
|
this.db = opts.db;
|
|
30365
30798
|
this.namespace = opts.namespace ?? "code";
|
|
30366
30799
|
this.extensions = new Set((opts.extensions ?? DEFAULT_EXTENSIONS).map((e) => e.replace(/^\./, "").toLowerCase()));
|
|
@@ -30392,14 +30825,14 @@ var WorkspaceIndex = class {
|
|
|
30392
30825
|
return;
|
|
30393
30826
|
}
|
|
30394
30827
|
for (const entry of entries) {
|
|
30395
|
-
const abs =
|
|
30828
|
+
const abs = path36__default.default.join(dir, entry.name);
|
|
30396
30829
|
if (entry.isDirectory()) {
|
|
30397
30830
|
if (HARD_SKIP_DIRS.has(entry.name) || this.isIgnored(abs)) continue;
|
|
30398
30831
|
await walk(abs);
|
|
30399
30832
|
} else if (entry.isFile()) {
|
|
30400
|
-
const ext =
|
|
30833
|
+
const ext = path36__default.default.extname(entry.name).slice(1).toLowerCase();
|
|
30401
30834
|
if (!this.extensions.has(ext) || this.isIgnored(abs)) continue;
|
|
30402
|
-
out.push(
|
|
30835
|
+
out.push(path36__default.default.relative(this.root, abs));
|
|
30403
30836
|
}
|
|
30404
30837
|
}
|
|
30405
30838
|
};
|
|
@@ -30429,7 +30862,7 @@ var WorkspaceIndex = class {
|
|
|
30429
30862
|
const entries = [];
|
|
30430
30863
|
for (const rel of rels) {
|
|
30431
30864
|
try {
|
|
30432
|
-
const abs =
|
|
30865
|
+
const abs = path36__default.default.join(this.root, rel);
|
|
30433
30866
|
const stat = await fs11__default.default.stat(abs);
|
|
30434
30867
|
if (stat.size > this.maxFileBytes) continue;
|
|
30435
30868
|
const buf = await fs11__default.default.readFile(abs);
|
|
@@ -30919,13 +31352,13 @@ var Cascade = class _Cascade extends EventEmitter__default.default {
|
|
|
30919
31352
|
this.toolRegistry = new ToolRegistry(this.config.tools, workspacePath);
|
|
30920
31353
|
try {
|
|
30921
31354
|
this.router.setDeadModelStore(new DeadModelStore(
|
|
30922
|
-
fileDeadModelPersistence(
|
|
31355
|
+
fileDeadModelPersistence(path36__default.default.join(workspacePath, ".cascade", "dead-models.json"))
|
|
30923
31356
|
));
|
|
30924
31357
|
} catch {
|
|
30925
31358
|
}
|
|
30926
31359
|
try {
|
|
30927
31360
|
this.resumeStore = new ResumeStore({
|
|
30928
|
-
dir:
|
|
31361
|
+
dir: path36__default.default.join(workspacePath, ".cascade", "resume")
|
|
30929
31362
|
});
|
|
30930
31363
|
} catch {
|
|
30931
31364
|
}
|
|
@@ -31013,8 +31446,8 @@ var Cascade = class _Cascade extends EventEmitter__default.default {
|
|
|
31013
31446
|
this.emit("log", { level: "warn", message: "Code index enabled but no embeddings-capable provider is configured \u2014 skipping." });
|
|
31014
31447
|
return;
|
|
31015
31448
|
}
|
|
31016
|
-
const dbPath = ci.dbPath ||
|
|
31017
|
-
|
|
31449
|
+
const dbPath = ci.dbPath || path36__default.default.join(this.workspacePath, ".cascade", "code-index.db");
|
|
31450
|
+
fs33__default.default.mkdirSync(path36__default.default.dirname(dbPath), { recursive: true });
|
|
31018
31451
|
const db = new Database2__default.default(dbPath);
|
|
31019
31452
|
db.pragma("journal_mode = WAL");
|
|
31020
31453
|
const complete = chatCompleterFromProviders(this.config.providers);
|
|
@@ -32482,14 +32915,14 @@ ${finalOutput}` : ""
|
|
|
32482
32915
|
init_constants();
|
|
32483
32916
|
var CLOUD_SESSION_FILE = "cloud-session.json";
|
|
32484
32917
|
function globalDir(homeDir = os10__default.default.homedir()) {
|
|
32485
|
-
return
|
|
32918
|
+
return path36__default.default.join(homeDir, GLOBAL_CONFIG_DIR);
|
|
32486
32919
|
}
|
|
32487
32920
|
function cloudSessionPath(dir = globalDir()) {
|
|
32488
|
-
return
|
|
32921
|
+
return path36__default.default.join(dir, CLOUD_SESSION_FILE);
|
|
32489
32922
|
}
|
|
32490
32923
|
function loadCloudSession(dir = globalDir()) {
|
|
32491
32924
|
try {
|
|
32492
|
-
const raw =
|
|
32925
|
+
const raw = fs33__default.default.readFileSync(cloudSessionPath(dir), "utf-8");
|
|
32493
32926
|
const parsed = JSON.parse(raw);
|
|
32494
32927
|
if (!parsed?.refreshToken || !parsed?.serverUrl) return null;
|
|
32495
32928
|
return parsed;
|
|
@@ -32498,17 +32931,17 @@ function loadCloudSession(dir = globalDir()) {
|
|
|
32498
32931
|
}
|
|
32499
32932
|
}
|
|
32500
32933
|
function saveCloudSession(session, dir = globalDir()) {
|
|
32501
|
-
|
|
32934
|
+
fs33__default.default.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
32502
32935
|
const file = cloudSessionPath(dir);
|
|
32503
|
-
|
|
32936
|
+
fs33__default.default.writeFileSync(file, JSON.stringify(session, null, 2), { mode: 384 });
|
|
32504
32937
|
try {
|
|
32505
|
-
|
|
32938
|
+
fs33__default.default.chmodSync(file, 384);
|
|
32506
32939
|
} catch {
|
|
32507
32940
|
}
|
|
32508
32941
|
}
|
|
32509
32942
|
function clearCloudSession(dir = globalDir()) {
|
|
32510
32943
|
try {
|
|
32511
|
-
|
|
32944
|
+
fs33__default.default.rmSync(cloudSessionPath(dir));
|
|
32512
32945
|
} catch {
|
|
32513
32946
|
}
|
|
32514
32947
|
}
|
|
@@ -32680,16 +33113,16 @@ var CloudClient = class _CloudClient {
|
|
|
32680
33113
|
return (await this.refresh()).accessToken;
|
|
32681
33114
|
}
|
|
32682
33115
|
/** Authenticated request that refreshes once on a 401 (e.g. server-side revoke). */
|
|
32683
|
-
async authed(
|
|
32684
|
-
const call = (token) => fetch(this.url(
|
|
33116
|
+
async authed(path41, init = {}) {
|
|
33117
|
+
const call = (token) => fetch(this.url(path41), { ...init, headers: { ...init.headers ?? {}, Authorization: `Bearer ${token}` } });
|
|
32685
33118
|
let res = await call(await this.accessToken());
|
|
32686
33119
|
if (res.status === 401) res = await call((await this.refresh()).accessToken);
|
|
32687
33120
|
if (!res.ok) throw new Error(`Request failed (${res.status}).`);
|
|
32688
33121
|
const text = await res.text();
|
|
32689
33122
|
return text ? JSON.parse(text) : {};
|
|
32690
33123
|
}
|
|
32691
|
-
authedGet(
|
|
32692
|
-
return this.authed(
|
|
33124
|
+
authedGet(path41) {
|
|
33125
|
+
return this.authed(path41);
|
|
32693
33126
|
}
|
|
32694
33127
|
async fetchMe(token) {
|
|
32695
33128
|
const res = await fetch(this.url("/api/me"), { headers: { Authorization: `Bearer ${token}` } });
|
|
@@ -34463,9 +34896,9 @@ function Repl({ config, workspacePath, themeName, initialPrompt, identityName, s
|
|
|
34463
34896
|
}
|
|
34464
34897
|
} catch {
|
|
34465
34898
|
}
|
|
34466
|
-
const configPath =
|
|
34899
|
+
const configPath = path36__default.default.join(workspacePath, ".cascade", "config.json");
|
|
34467
34900
|
try {
|
|
34468
|
-
await fs11__default.default.mkdir(
|
|
34901
|
+
await fs11__default.default.mkdir(path36__default.default.dirname(configPath), { recursive: true });
|
|
34469
34902
|
await fs11__default.default.writeFile(configPath, JSON.stringify(config, null, 2), "utf-8");
|
|
34470
34903
|
} catch (err) {
|
|
34471
34904
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -34517,9 +34950,9 @@ function Repl({ config, workspacePath, themeName, initialPrompt, identityName, s
|
|
|
34517
34950
|
if (msg.includes("non-text parts")) return;
|
|
34518
34951
|
originalLog(...args);
|
|
34519
34952
|
};
|
|
34520
|
-
const store = new MemoryStore(
|
|
34953
|
+
const store = new MemoryStore(path36__default.default.join(workspacePath, CASCADE_DB_FILE));
|
|
34521
34954
|
storeRef.current = store;
|
|
34522
|
-
globalStoreRef.current = new MemoryStore(
|
|
34955
|
+
globalStoreRef.current = new MemoryStore(path36__default.default.join(os10__default.default.homedir(), GLOBAL_CONFIG_DIR, GLOBAL_RUNTIME_DB_FILE));
|
|
34523
34956
|
const identityRows = store.listIdentities().map((i) => ({ id: i.id, name: i.name, isDefault: i.isDefault }));
|
|
34524
34957
|
setIdentities(identityRows);
|
|
34525
34958
|
let initialIdentityId = config.defaultIdentityId ?? identityRows.find((i) => i.isDefault)?.id ?? identityRows[0]?.id;
|
|
@@ -34599,7 +35032,7 @@ function Repl({ config, workspacePath, themeName, initialPrompt, identityName, s
|
|
|
34599
35032
|
onThemeChange: (name) => setTheme(getTheme(name)),
|
|
34600
35033
|
onExport: async (fmt) => {
|
|
34601
35034
|
const stamp2 = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
34602
|
-
const exportPath =
|
|
35035
|
+
const exportPath = path36__default.default.join(workspacePath, `cascade-export-${stamp2}.${fmt === "json" ? "json" : "md"}`);
|
|
34603
35036
|
if (fmt === "json") {
|
|
34604
35037
|
await fs11__default.default.writeFile(exportPath, JSON.stringify({ sessionId: sessionIdRef.current, messages: state.messages }, null, 2), "utf-8");
|
|
34605
35038
|
} else {
|
|
@@ -35519,7 +35952,7 @@ function stringifySlashOutput(val) {
|
|
|
35519
35952
|
}
|
|
35520
35953
|
async function searchSessionsAndMessages(query, workspacePath) {
|
|
35521
35954
|
if (!query) return "Usage: /search <query>";
|
|
35522
|
-
const dbPath =
|
|
35955
|
+
const dbPath = path36__default.default.join(workspacePath, CASCADE_DB_FILE);
|
|
35523
35956
|
try {
|
|
35524
35957
|
await fs11__default.default.access(dbPath);
|
|
35525
35958
|
} catch {
|
|
@@ -35553,7 +35986,7 @@ async function searchSessionsAndMessages(query, workspacePath) {
|
|
|
35553
35986
|
async function diagnoseRuntime(config, workspacePath) {
|
|
35554
35987
|
const providers = config.providers.map((p) => `${p.type}${p.apiKey ? " (key set)" : " (no key)"}`).join("\n");
|
|
35555
35988
|
const models = [`T1: ${config.models.t1 ?? "default"}`, `T2: ${config.models.t2 ?? "default"}`, `T3: ${config.models.t3 ?? "default"}`].join("\n");
|
|
35556
|
-
const store = new MemoryStore(
|
|
35989
|
+
const store = new MemoryStore(path36__default.default.join(workspacePath, CASCADE_DB_FILE));
|
|
35557
35990
|
try {
|
|
35558
35991
|
const sessions2 = store.listSessions(void 0, 3);
|
|
35559
35992
|
return [
|
|
@@ -35572,7 +36005,7 @@ async function diagnoseRuntime(config, workspacePath) {
|
|
|
35572
36005
|
}
|
|
35573
36006
|
async function showRecentLogs(args, workspacePath) {
|
|
35574
36007
|
const limit = Number.parseInt(args[0] ?? "10", 10) || 10;
|
|
35575
|
-
const store = new MemoryStore(
|
|
36008
|
+
const store = new MemoryStore(path36__default.default.join(workspacePath, CASCADE_DB_FILE));
|
|
35576
36009
|
try {
|
|
35577
36010
|
const logs = store.listRuntimeNodeLogs(void 0, void 0, limit);
|
|
35578
36011
|
if (!logs.length) return "No recent runtime logs.";
|
|
@@ -35584,7 +36017,7 @@ async function showRecentLogs(args, workspacePath) {
|
|
|
35584
36017
|
async function loadSessionSnapshot(args, workspacePath) {
|
|
35585
36018
|
const sessionId = args[0];
|
|
35586
36019
|
if (!sessionId) return "Usage: /resume <sessionId>";
|
|
35587
|
-
const store = new MemoryStore(
|
|
36020
|
+
const store = new MemoryStore(path36__default.default.join(workspacePath, CASCADE_DB_FILE));
|
|
35588
36021
|
try {
|
|
35589
36022
|
const session = store.getSession(sessionId);
|
|
35590
36023
|
if (!session) return `Session not found: ${sessionId}`;
|
|
@@ -36004,9 +36437,9 @@ function SetupWizard({ workspacePath, onComplete }) {
|
|
|
36004
36437
|
...anyAuto ? { cascadeAuto: true } : {}
|
|
36005
36438
|
};
|
|
36006
36439
|
const config = CascadeConfigSchema.parse(rawConfig);
|
|
36007
|
-
const configDir =
|
|
36440
|
+
const configDir = path36__default.default.join(workspacePath, ".cascade");
|
|
36008
36441
|
await fs11__default.default.mkdir(configDir, { recursive: true });
|
|
36009
|
-
const configPath =
|
|
36442
|
+
const configPath = path36__default.default.join(workspacePath, CASCADE_CONFIG_FILE);
|
|
36010
36443
|
await fs11__default.default.writeFile(configPath, JSON.stringify(config, null, 2), "utf-8");
|
|
36011
36444
|
savedConfigRef.current = config;
|
|
36012
36445
|
dispatchRef.current({ type: "GO_DONE" });
|
|
@@ -36347,14 +36780,14 @@ function printTelemetryBanner() {
|
|
|
36347
36780
|
async function initCommand(workspacePath = process.cwd()) {
|
|
36348
36781
|
const spin = ora__default.default({ text: "Initializing Cascade project\u2026", color: "magenta" }).start();
|
|
36349
36782
|
try {
|
|
36350
|
-
const configDir =
|
|
36783
|
+
const configDir = path36__default.default.join(workspacePath, ".cascade");
|
|
36351
36784
|
await fs11__default.default.mkdir(configDir, { recursive: true });
|
|
36352
|
-
const mdPath =
|
|
36785
|
+
const mdPath = path36__default.default.join(workspacePath, "CASCADE.md");
|
|
36353
36786
|
if (!await fileExists(mdPath)) {
|
|
36354
36787
|
await createDefaultCascadeMd(workspacePath);
|
|
36355
36788
|
spin.succeed(chalk8__default.default.green("Created CASCADE.md"));
|
|
36356
36789
|
}
|
|
36357
|
-
const ignorePath =
|
|
36790
|
+
const ignorePath = path36__default.default.join(workspacePath, ".cascadeignore");
|
|
36358
36791
|
if (!await fileExists(ignorePath)) {
|
|
36359
36792
|
await createDefaultIgnoreFile(workspacePath);
|
|
36360
36793
|
spin.succeed(chalk8__default.default.green("Created .cascadeignore"));
|
|
@@ -36363,7 +36796,7 @@ async function initCommand(workspacePath = process.cwd()) {
|
|
|
36363
36796
|
console.log();
|
|
36364
36797
|
console.log(chalk8__default.default.magenta(" \u25C8 Cascade AI \u2014 Project initialized"));
|
|
36365
36798
|
console.log();
|
|
36366
|
-
const configPath =
|
|
36799
|
+
const configPath = path36__default.default.join(workspacePath, CASCADE_CONFIG_FILE);
|
|
36367
36800
|
if (await fileExists(configPath)) {
|
|
36368
36801
|
console.log(chalk8__default.default.yellow(" .cascade/config.json already exists \u2014 launching wizard to reconfigure."));
|
|
36369
36802
|
console.log();
|
|
@@ -36514,8 +36947,8 @@ function fromEnv(env) {
|
|
|
36514
36947
|
return out;
|
|
36515
36948
|
}
|
|
36516
36949
|
async function fromClaudeCode(home, env) {
|
|
36517
|
-
const dir = str(env["CLAUDE_CONFIG_DIR"]) ??
|
|
36518
|
-
const file =
|
|
36950
|
+
const dir = str(env["CLAUDE_CONFIG_DIR"]) ?? path36__default.default.join(home, ".claude");
|
|
36951
|
+
const file = path36__default.default.join(dir, ".credentials.json");
|
|
36519
36952
|
const data = await readJson(file);
|
|
36520
36953
|
if (!data) return [];
|
|
36521
36954
|
const found = [];
|
|
@@ -36539,7 +36972,7 @@ async function fromClaudeCode(home, env) {
|
|
|
36539
36972
|
return found;
|
|
36540
36973
|
}
|
|
36541
36974
|
async function fromCodex(home) {
|
|
36542
|
-
const file =
|
|
36975
|
+
const file = path36__default.default.join(home, ".codex", "auth.json");
|
|
36543
36976
|
const data = await readJson(file);
|
|
36544
36977
|
if (!data) return [];
|
|
36545
36978
|
const apiKey = str(data["OPENAI_API_KEY"]);
|
|
@@ -36562,7 +36995,7 @@ async function fromCodex(home) {
|
|
|
36562
36995
|
return [];
|
|
36563
36996
|
}
|
|
36564
36997
|
async function fromGemini(home) {
|
|
36565
|
-
const file =
|
|
36998
|
+
const file = path36__default.default.join(home, ".gemini", "oauth_creds.json");
|
|
36566
36999
|
const data = await readJson(file);
|
|
36567
37000
|
const accessToken = str(data?.["access_token"]);
|
|
36568
37001
|
if (!accessToken) return [];
|
|
@@ -36578,7 +37011,7 @@ async function fromGemini(home) {
|
|
|
36578
37011
|
}
|
|
36579
37012
|
async function fromCopilot(home) {
|
|
36580
37013
|
for (const name of ["apps.json", "hosts.json"]) {
|
|
36581
|
-
const file =
|
|
37014
|
+
const file = path36__default.default.join(home, ".config", "github-copilot", name);
|
|
36582
37015
|
const data = await readJson(file);
|
|
36583
37016
|
if (!data) continue;
|
|
36584
37017
|
for (const value of Object.values(data)) {
|
|
@@ -36879,7 +37312,7 @@ async function doctorCommand() {
|
|
|
36879
37312
|
checks.push({
|
|
36880
37313
|
label: "Cascade config",
|
|
36881
37314
|
ok: true,
|
|
36882
|
-
detail: `Loaded ${
|
|
37315
|
+
detail: `Loaded ${path36__default.default.join(process.cwd(), CASCADE_CONFIG_FILE)}`
|
|
36883
37316
|
});
|
|
36884
37317
|
const providers = [
|
|
36885
37318
|
{ type: "anthropic", name: "Anthropic" },
|
|
@@ -36989,7 +37422,7 @@ async function checkEndpoint(url) {
|
|
|
36989
37422
|
}
|
|
36990
37423
|
}
|
|
36991
37424
|
async function indexCommand(dirPath) {
|
|
36992
|
-
const workspace =
|
|
37425
|
+
const workspace = path36__default.default.resolve(dirPath || process.cwd());
|
|
36993
37426
|
const cm = new ConfigManager(workspace);
|
|
36994
37427
|
await cm.load();
|
|
36995
37428
|
const config = cm.getConfig();
|
|
@@ -37000,8 +37433,8 @@ async function indexCommand(dirPath) {
|
|
|
37000
37433
|
process.exitCode = 1;
|
|
37001
37434
|
return;
|
|
37002
37435
|
}
|
|
37003
|
-
const dbPath = config.codeIndex?.dbPath ||
|
|
37004
|
-
|
|
37436
|
+
const dbPath = config.codeIndex?.dbPath || path36__default.default.join(workspace, ".cascade", "code-index.db");
|
|
37437
|
+
fs33__default.default.mkdirSync(path36__default.default.dirname(dbPath), { recursive: true });
|
|
37005
37438
|
const db = new Database2__default.default(dbPath);
|
|
37006
37439
|
db.pragma("journal_mode = WAL");
|
|
37007
37440
|
const complete = chatCompleterFromProviders(config.providers);
|
|
@@ -37533,7 +37966,7 @@ function openBrowser2(url) {
|
|
|
37533
37966
|
}
|
|
37534
37967
|
function storePathFor(name) {
|
|
37535
37968
|
const safe = name.replace(/[^a-z0-9._-]/gi, "_").slice(0, 64) || "server";
|
|
37536
|
-
return
|
|
37969
|
+
return path36__default.default.join(os10__default.default.homedir(), ".cascade-ai", "mcp-oauth", `${safe}.json`);
|
|
37537
37970
|
}
|
|
37538
37971
|
function defaultName(url) {
|
|
37539
37972
|
try {
|
|
@@ -37920,8 +38353,8 @@ function replaceInPlace(target, source) {
|
|
|
37920
38353
|
}
|
|
37921
38354
|
function writeConfigFile(configPath, config) {
|
|
37922
38355
|
try {
|
|
37923
|
-
|
|
37924
|
-
|
|
38356
|
+
fs33__default.default.mkdirSync(path36__default.default.dirname(configPath), { recursive: true });
|
|
38357
|
+
fs33__default.default.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
|
|
37925
38358
|
return { ok: true };
|
|
37926
38359
|
} catch (err) {
|
|
37927
38360
|
return { ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
@@ -38337,7 +38770,7 @@ function aggregateCostStats(sessions2, opts = {}) {
|
|
|
38337
38770
|
}
|
|
38338
38771
|
|
|
38339
38772
|
// src/dashboard/server.ts
|
|
38340
|
-
var __dirname$1 =
|
|
38773
|
+
var __dirname$1 = path36__default.default.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli.cjs', document.baseURI).href))));
|
|
38341
38774
|
var ORPHANED_ESCALATION_GRACE_MS = 3e4;
|
|
38342
38775
|
var MASK = "***";
|
|
38343
38776
|
function masked(key, value) {
|
|
@@ -38656,7 +39089,7 @@ var DashboardServer = class {
|
|
|
38656
39089
|
* silently and still typecheck.
|
|
38657
39090
|
*/
|
|
38658
39091
|
persistConfig(config) {
|
|
38659
|
-
const result = writeConfigFile(
|
|
39092
|
+
const result = writeConfigFile(path36__default.default.join(this.workspacePath, CASCADE_CONFIG_FILE), config);
|
|
38660
39093
|
if (!result.ok) console.warn(`[dashboard] Failed to persist config: ${result.error}`);
|
|
38661
39094
|
return result;
|
|
38662
39095
|
}
|
|
@@ -38675,7 +39108,7 @@ var DashboardServer = class {
|
|
|
38675
39108
|
*/
|
|
38676
39109
|
syncGlobalCredentials() {
|
|
38677
39110
|
try {
|
|
38678
|
-
saveGlobalCredentials(
|
|
39111
|
+
saveGlobalCredentials(path36__default.default.join(os10__default.default.homedir(), GLOBAL_CONFIG_DIR), this.config.providers ?? []);
|
|
38679
39112
|
} catch (err) {
|
|
38680
39113
|
console.warn(`[dashboard] Failed to sync global credentials: ${err instanceof Error ? err.message : String(err)}`);
|
|
38681
39114
|
}
|
|
@@ -38690,15 +39123,15 @@ var DashboardServer = class {
|
|
|
38690
39123
|
resolveDashboardSecret() {
|
|
38691
39124
|
const fromConfig = this.config.dashboard.secret ?? process.env["CASCADE_DASHBOARD_SECRET"];
|
|
38692
39125
|
if (fromConfig) return fromConfig;
|
|
38693
|
-
const secretPath =
|
|
39126
|
+
const secretPath = path36__default.default.join(this.workspacePath, CASCADE_DASHBOARD_SECRET_FILE);
|
|
38694
39127
|
try {
|
|
38695
|
-
if (
|
|
38696
|
-
const existing =
|
|
39128
|
+
if (fs33__default.default.existsSync(secretPath)) {
|
|
39129
|
+
const existing = fs33__default.default.readFileSync(secretPath, "utf-8").trim();
|
|
38697
39130
|
if (existing.length >= 16) return existing;
|
|
38698
39131
|
}
|
|
38699
39132
|
const generated = crypto.randomUUID();
|
|
38700
|
-
|
|
38701
|
-
|
|
39133
|
+
fs33__default.default.mkdirSync(path36__default.default.dirname(secretPath), { recursive: true });
|
|
39134
|
+
fs33__default.default.writeFileSync(secretPath, generated, { encoding: "utf-8", mode: 384 });
|
|
38702
39135
|
if (this.config.dashboard.auth) {
|
|
38703
39136
|
console.warn(
|
|
38704
39137
|
`Dashboard auth enabled with no secret configured; persisted a generated secret to ${secretPath}. Set CASCADE_DASHBOARD_SECRET or config.dashboard.secret to override.`
|
|
@@ -38725,7 +39158,7 @@ var DashboardServer = class {
|
|
|
38725
39158
|
// ── Setup ─────────────────────────────────────
|
|
38726
39159
|
getGlobalStore() {
|
|
38727
39160
|
if (!this.globalStore) {
|
|
38728
|
-
const globalDbPath =
|
|
39161
|
+
const globalDbPath = path36__default.default.join(os10__default.default.homedir(), GLOBAL_CONFIG_DIR, GLOBAL_RUNTIME_DB_FILE);
|
|
38729
39162
|
this.globalStore = new MemoryStore(globalDbPath);
|
|
38730
39163
|
}
|
|
38731
39164
|
return this.globalStore;
|
|
@@ -39105,12 +39538,12 @@ ${prompt}`;
|
|
|
39105
39538
|
}
|
|
39106
39539
|
}
|
|
39107
39540
|
watchRuntimeChanges() {
|
|
39108
|
-
const workspaceDbPath =
|
|
39109
|
-
const globalDbPath =
|
|
39541
|
+
const workspaceDbPath = path36__default.default.join(this.workspacePath, CASCADE_DB_FILE);
|
|
39542
|
+
const globalDbPath = path36__default.default.join(os10__default.default.homedir(), GLOBAL_CONFIG_DIR, GLOBAL_RUNTIME_DB_FILE);
|
|
39110
39543
|
const watchPaths = [workspaceDbPath, globalDbPath].filter((p, index, arr) => arr.indexOf(p) === index);
|
|
39111
39544
|
for (const watchPath of watchPaths) {
|
|
39112
|
-
if (!
|
|
39113
|
-
|
|
39545
|
+
if (!fs33__default.default.existsSync(watchPath)) continue;
|
|
39546
|
+
fs33__default.default.watchFile(watchPath, { interval: 3e3 }, () => {
|
|
39114
39547
|
this.throttledBroadcast(watchPath === globalDbPath ? "global" : "workspace");
|
|
39115
39548
|
});
|
|
39116
39549
|
}
|
|
@@ -39232,7 +39665,7 @@ ${prompt}`;
|
|
|
39232
39665
|
const sessionId = req.params.id;
|
|
39233
39666
|
this.store.deleteSession(sessionId);
|
|
39234
39667
|
this.store.deleteRuntimeSession(sessionId);
|
|
39235
|
-
const globalDbPath =
|
|
39668
|
+
const globalDbPath = path36__default.default.join(os10__default.default.homedir(), GLOBAL_CONFIG_DIR, GLOBAL_RUNTIME_DB_FILE);
|
|
39236
39669
|
const globalStore = new MemoryStore(globalDbPath);
|
|
39237
39670
|
try {
|
|
39238
39671
|
globalStore.deleteRuntimeSession(sessionId);
|
|
@@ -39325,7 +39758,7 @@ ${prompt}`;
|
|
|
39325
39758
|
});
|
|
39326
39759
|
this.app.delete("/api/sessions", auth2, (req, res) => {
|
|
39327
39760
|
const body = req.body;
|
|
39328
|
-
const globalDbPath =
|
|
39761
|
+
const globalDbPath = path36__default.default.join(os10__default.default.homedir(), GLOBAL_CONFIG_DIR, GLOBAL_RUNTIME_DB_FILE);
|
|
39329
39762
|
if (body?.ids && Array.isArray(body.ids) && body.ids.length > 0) {
|
|
39330
39763
|
const globalStore = new MemoryStore(globalDbPath);
|
|
39331
39764
|
try {
|
|
@@ -39348,7 +39781,7 @@ ${prompt}`;
|
|
|
39348
39781
|
});
|
|
39349
39782
|
this.app.delete("/api/runtime", auth2, (_req, res) => {
|
|
39350
39783
|
this.store.deleteAllRuntimeNodes();
|
|
39351
|
-
const globalDbPath =
|
|
39784
|
+
const globalDbPath = path36__default.default.join(os10__default.default.homedir(), GLOBAL_CONFIG_DIR, GLOBAL_RUNTIME_DB_FILE);
|
|
39352
39785
|
const globalStore = new MemoryStore(globalDbPath);
|
|
39353
39786
|
try {
|
|
39354
39787
|
globalStore.deleteAllRuntimeNodes();
|
|
@@ -39433,12 +39866,12 @@ ${prompt}`;
|
|
|
39433
39866
|
if (body["tierLimits"]) this.config.tierLimits = { ...this.config.tierLimits, ...body["tierLimits"] };
|
|
39434
39867
|
if (body["budget"]) this.config.budget = { ...this.config.budget, ...body["budget"] };
|
|
39435
39868
|
try {
|
|
39436
|
-
const configPath =
|
|
39437
|
-
const existing =
|
|
39869
|
+
const configPath = path36__default.default.join(this.workspacePath, CASCADE_CONFIG_FILE);
|
|
39870
|
+
const existing = fs33__default.default.existsSync(configPath) ? JSON.parse(fs33__default.default.readFileSync(configPath, "utf-8")) : {};
|
|
39438
39871
|
const updated = { ...existing, tierLimits: this.config.tierLimits, budget: this.config.budget };
|
|
39439
39872
|
const tmp = configPath + ".tmp";
|
|
39440
|
-
|
|
39441
|
-
|
|
39873
|
+
fs33__default.default.writeFileSync(tmp, JSON.stringify(updated, null, 2), "utf-8");
|
|
39874
|
+
fs33__default.default.renameSync(tmp, configPath);
|
|
39442
39875
|
res.json({ ok: true });
|
|
39443
39876
|
} catch (err) {
|
|
39444
39877
|
res.status(500).json({ error: `Failed to save config: ${err instanceof Error ? err.message : String(err)}` });
|
|
@@ -39466,7 +39899,7 @@ ${prompt}`;
|
|
|
39466
39899
|
this.app.get("/api/runtime", auth2, (req, res) => {
|
|
39467
39900
|
const scope = req.query["scope"] ?? "workspace";
|
|
39468
39901
|
if (scope === "global") {
|
|
39469
|
-
const globalDbPath =
|
|
39902
|
+
const globalDbPath = path36__default.default.join(os10__default.default.homedir(), GLOBAL_CONFIG_DIR, GLOBAL_RUNTIME_DB_FILE);
|
|
39470
39903
|
const globalStore = new MemoryStore(globalDbPath);
|
|
39471
39904
|
try {
|
|
39472
39905
|
res.json({
|
|
@@ -39807,13 +40240,13 @@ ${prompt}`;
|
|
|
39807
40240
|
res.status(500).json({ error: err instanceof Error ? err.message : String(err) });
|
|
39808
40241
|
}
|
|
39809
40242
|
});
|
|
39810
|
-
const prodPath =
|
|
39811
|
-
const devPath =
|
|
39812
|
-
const webDistPath =
|
|
39813
|
-
if (
|
|
40243
|
+
const prodPath = path36__default.default.resolve(__dirname$1, "../web/dist");
|
|
40244
|
+
const devPath = path36__default.default.resolve(__dirname$1, "../../web/dist");
|
|
40245
|
+
const webDistPath = fs33__default.default.existsSync(prodPath) ? prodPath : devPath;
|
|
40246
|
+
if (fs33__default.default.existsSync(webDistPath)) {
|
|
39814
40247
|
this.app.use(express__default.default.static(webDistPath));
|
|
39815
40248
|
this.app.get("*", (_req, res) => {
|
|
39816
|
-
res.sendFile(
|
|
40249
|
+
res.sendFile(path36__default.default.join(webDistPath, "index.html"));
|
|
39817
40250
|
});
|
|
39818
40251
|
} else {
|
|
39819
40252
|
this.app.get("/", (_req, res) => {
|
|
@@ -39834,7 +40267,7 @@ init_constants();
|
|
|
39834
40267
|
async function dashboardCommand(config, workspacePath = process.cwd()) {
|
|
39835
40268
|
const port = config.dashboard.port ?? DEFAULT_DASHBOARD_PORT;
|
|
39836
40269
|
const spin = ora__default.default({ text: `Starting dashboard on port ${port}\u2026`, color: "magenta" }).start();
|
|
39837
|
-
const store = new MemoryStore(
|
|
40270
|
+
const store = new MemoryStore(path36__default.default.join(workspacePath, CASCADE_DB_FILE));
|
|
39838
40271
|
const server = new DashboardServer(config, store, workspacePath);
|
|
39839
40272
|
server.watchRuntimeChanges();
|
|
39840
40273
|
const gThis = globalThis;
|
|
@@ -39866,7 +40299,7 @@ init_constants();
|
|
|
39866
40299
|
function makeIdentityCommand(workspacePath = process.cwd()) {
|
|
39867
40300
|
const identity = new commander.Command("identity").alias("id").description("Manage Cascade identities");
|
|
39868
40301
|
identity.command("list").description("List all available identities").action(() => {
|
|
39869
|
-
const store = new MemoryStore(
|
|
40302
|
+
const store = new MemoryStore(path36__default.default.join(workspacePath, CASCADE_DB_FILE));
|
|
39870
40303
|
try {
|
|
39871
40304
|
const identities = store.listIdentities();
|
|
39872
40305
|
console.log(chalk8__default.default.bold("\n Identities:"));
|
|
@@ -39886,7 +40319,7 @@ function makeIdentityCommand(workspacePath = process.cwd()) {
|
|
|
39886
40319
|
}
|
|
39887
40320
|
});
|
|
39888
40321
|
identity.command("create <name>").description("Create a new identity").option("-d, --desc <text>", "Description of the identity").option("-s, --system <text>", "System prompt").option("--default", "Set as default identity").action((name, options) => {
|
|
39889
|
-
const store = new MemoryStore(
|
|
40322
|
+
const store = new MemoryStore(path36__default.default.join(workspacePath, CASCADE_DB_FILE));
|
|
39890
40323
|
try {
|
|
39891
40324
|
if (options.default) {
|
|
39892
40325
|
const existingDefault = store.getDefaultIdentity();
|
|
@@ -39912,7 +40345,7 @@ function makeIdentityCommand(workspacePath = process.cwd()) {
|
|
|
39912
40345
|
}
|
|
39913
40346
|
});
|
|
39914
40347
|
identity.command("set-default <name>").description("Set an identity as default by name or ID").action((query) => {
|
|
39915
|
-
const store = new MemoryStore(
|
|
40348
|
+
const store = new MemoryStore(path36__default.default.join(workspacePath, CASCADE_DB_FILE));
|
|
39916
40349
|
try {
|
|
39917
40350
|
const identities = store.listIdentities();
|
|
39918
40351
|
const match = identities.find((i) => i.id === query || i.name.toLowerCase() === query.toLowerCase());
|
|
@@ -40061,8 +40494,8 @@ async function exportCommand(options = {}) {
|
|
|
40061
40494
|
let store;
|
|
40062
40495
|
try {
|
|
40063
40496
|
const workspacePath = options.workspacePath ?? process.cwd();
|
|
40064
|
-
const workspaceDbPath =
|
|
40065
|
-
const globalDbPath =
|
|
40497
|
+
const workspaceDbPath = path36__default.default.join(workspacePath, CASCADE_DB_FILE);
|
|
40498
|
+
const globalDbPath = path36__default.default.join(os10__default.default.homedir(), GLOBAL_CONFIG_DIR, GLOBAL_DB_FILE);
|
|
40066
40499
|
let dbPath = globalDbPath;
|
|
40067
40500
|
try {
|
|
40068
40501
|
await fs11__default.default.access(workspaceDbPath);
|
|
@@ -40104,7 +40537,7 @@ async function exportCommand(options = {}) {
|
|
|
40104
40537
|
const ext = format === "json" ? ".json" : ".md";
|
|
40105
40538
|
const safeName = session.title.replace(/[^\w\s-]/g, "").replace(/\s+/g, "-").slice(0, 60);
|
|
40106
40539
|
const defaultFile = `cascade-export-${safeName}${ext}`;
|
|
40107
|
-
const outPath = options.output ?
|
|
40540
|
+
const outPath = options.output ? path36__default.default.resolve(options.output) : path36__default.default.join(process.cwd(), defaultFile);
|
|
40108
40541
|
await fs11__default.default.writeFile(outPath, content, "utf-8");
|
|
40109
40542
|
spin.succeed(chalk8__default.default.green(`Exported to ${chalk8__default.default.white(outPath)}`));
|
|
40110
40543
|
const messageCount = Array.isArray(session.messages) ? session.messages.length : 0;
|
|
@@ -40244,7 +40677,7 @@ var SHOW_CURSOR = "\x1B[?25h";
|
|
|
40244
40677
|
function writeNow(stdout, text) {
|
|
40245
40678
|
if (typeof stdout.fd === "number") {
|
|
40246
40679
|
try {
|
|
40247
|
-
|
|
40680
|
+
fs33__default.default.writeSync(stdout.fd, text);
|
|
40248
40681
|
return;
|
|
40249
40682
|
} catch {
|
|
40250
40683
|
}
|
|
@@ -40267,11 +40700,11 @@ function restoreTerminal(stdin, stdout) {
|
|
|
40267
40700
|
dotenv__default.default.config();
|
|
40268
40701
|
function warnIfBuildIsStale() {
|
|
40269
40702
|
try {
|
|
40270
|
-
const here =
|
|
40703
|
+
const here = path36__default.default.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli.cjs', document.baseURI).href))));
|
|
40271
40704
|
for (const rel of ["..", "../.."]) {
|
|
40272
|
-
const pkgPath =
|
|
40273
|
-
if (!
|
|
40274
|
-
const pkg = JSON.parse(
|
|
40705
|
+
const pkgPath = path36__default.default.join(here, rel, "package.json");
|
|
40706
|
+
if (!fs33__default.default.existsSync(pkgPath)) continue;
|
|
40707
|
+
const pkg = JSON.parse(fs33__default.default.readFileSync(pkgPath, "utf-8"));
|
|
40275
40708
|
if (pkg.name !== "cascade-ai") continue;
|
|
40276
40709
|
if (pkg.version && pkg.version !== CASCADE_VERSION) {
|
|
40277
40710
|
console.error(
|