lupacode 0.2.5 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1795 -579
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -70792,9 +70792,6 @@ var SplitBorderChars = {
|
|
|
70792
70792
|
|
|
70793
70793
|
// src/providers/theme/index.tsx
|
|
70794
70794
|
var import_react18 = __toESM(require_react(), 1);
|
|
70795
|
-
import { mkdirSync, readFileSync, writeFileSync as writeFileSync2 } from "fs";
|
|
70796
|
-
import { homedir } from "os";
|
|
70797
|
-
import { join as join2 } from "path";
|
|
70798
70795
|
|
|
70799
70796
|
// src/theme.ts
|
|
70800
70797
|
var THEMES = [
|
|
@@ -70804,7 +70801,7 @@ var THEMES = [
|
|
|
70804
70801
|
primary: "#719cd6",
|
|
70805
70802
|
planMode: "#db9b59",
|
|
70806
70803
|
selectMode: "#b55c7a",
|
|
70807
|
-
thinking: "#
|
|
70804
|
+
thinking: "#9DDAF6",
|
|
70808
70805
|
success: "#81b29a",
|
|
70809
70806
|
error: "#c94f6d",
|
|
70810
70807
|
info: "#7dcfff",
|
|
@@ -70923,7 +70920,7 @@ var THEMES = [
|
|
|
70923
70920
|
primary: "#C4A7E7",
|
|
70924
70921
|
planMode: "#F6C177",
|
|
70925
70922
|
selectMode: "#9CCFD8",
|
|
70926
|
-
thinking: "#
|
|
70923
|
+
thinking: "#9CCFD8",
|
|
70927
70924
|
success: "#9CCFD8",
|
|
70928
70925
|
error: "#EB6F92",
|
|
70929
70926
|
info: "#C4A7E7",
|
|
@@ -71035,343 +71032,354 @@ var THEMES = [
|
|
|
71035
71032
|
thinkingBorder: "#22DA6E",
|
|
71036
71033
|
dimSeparator: "#5F7E97"
|
|
71037
71034
|
}
|
|
71038
|
-
}
|
|
71039
|
-
|
|
71040
|
-
|
|
71041
|
-
|
|
71042
|
-
|
|
71043
|
-
|
|
71044
|
-
|
|
71045
|
-
|
|
71046
|
-
|
|
71047
|
-
|
|
71048
|
-
|
|
71049
|
-
|
|
71050
|
-
|
|
71051
|
-
|
|
71052
|
-
|
|
71053
|
-
|
|
71054
|
-
return DEFAULT_THEME;
|
|
71055
|
-
}
|
|
71056
|
-
}
|
|
71057
|
-
function persistTheme(theme) {
|
|
71058
|
-
try {
|
|
71059
|
-
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
71060
|
-
writeFileSync2(THEME_PREFERENCES_PATH, JSON.stringify({ themeName: theme.name }, null, 2), "utf8");
|
|
71061
|
-
} catch {}
|
|
71062
|
-
}
|
|
71063
|
-
var ThemeContext = import_react18.createContext(null);
|
|
71064
|
-
function useTheme() {
|
|
71065
|
-
const value = import_react18.useContext(ThemeContext);
|
|
71066
|
-
if (!value) {
|
|
71067
|
-
throw new Error("useTheme must be used within a ThemeProvider");
|
|
71068
|
-
}
|
|
71069
|
-
return value;
|
|
71070
|
-
}
|
|
71071
|
-
function ThemeProvider({ children }) {
|
|
71072
|
-
const [currentTheme, setCurrentTheme] = import_react18.useState(getInitialTheme);
|
|
71073
|
-
const setTheme = import_react18.useCallback((theme) => {
|
|
71074
|
-
setCurrentTheme(theme);
|
|
71075
|
-
persistTheme(theme);
|
|
71076
|
-
}, []);
|
|
71077
|
-
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(ThemeContext.Provider, {
|
|
71078
|
-
value: { colors: currentTheme.colors, currentTheme, setTheme },
|
|
71079
|
-
children
|
|
71080
|
-
}, undefined, false, undefined, this);
|
|
71081
|
-
}
|
|
71082
|
-
|
|
71083
|
-
// src/providers/toast/index.tsx
|
|
71084
|
-
var ToastContext = import_react19.createContext(null);
|
|
71085
|
-
function useToast() {
|
|
71086
|
-
const value = import_react19.useContext(ToastContext);
|
|
71087
|
-
if (!value) {
|
|
71088
|
-
throw new Error("useToast must be used within a ToastProvider");
|
|
71089
|
-
}
|
|
71090
|
-
return value;
|
|
71091
|
-
}
|
|
71092
|
-
function ToastProvider({ children }) {
|
|
71093
|
-
const [currentToast, setCurrentToast] = import_react19.useState(null);
|
|
71094
|
-
const timeoutHandleRef = import_react19.useRef(null);
|
|
71095
|
-
const clearCurrentTimeout = import_react19.useCallback(() => {
|
|
71096
|
-
if (timeoutHandleRef.current) {
|
|
71097
|
-
clearTimeout(timeoutHandleRef.current);
|
|
71098
|
-
timeoutHandleRef.current = null;
|
|
71035
|
+
},
|
|
71036
|
+
{
|
|
71037
|
+
name: "Everforest Dark",
|
|
71038
|
+
colors: {
|
|
71039
|
+
primary: "#7FBBB3",
|
|
71040
|
+
planMode: "#DBBC7F",
|
|
71041
|
+
selectMode: "#D699B6",
|
|
71042
|
+
thinking: "#A7C080",
|
|
71043
|
+
success: "#A7C080",
|
|
71044
|
+
error: "#E67E80",
|
|
71045
|
+
info: "#83C092",
|
|
71046
|
+
background: "#2D353B",
|
|
71047
|
+
surface: "#343F44",
|
|
71048
|
+
dialogSurface: "#3D484D",
|
|
71049
|
+
thinkingBorder: "#A7C080",
|
|
71050
|
+
dimSeparator: "#4F585E"
|
|
71099
71051
|
}
|
|
71100
|
-
},
|
|
71101
|
-
|
|
71102
|
-
|
|
71103
|
-
|
|
71104
|
-
|
|
71105
|
-
|
|
71106
|
-
|
|
71107
|
-
|
|
71108
|
-
|
|
71109
|
-
|
|
71110
|
-
|
|
71111
|
-
|
|
71112
|
-
|
|
71113
|
-
|
|
71114
|
-
|
|
71115
|
-
|
|
71116
|
-
children: [
|
|
71117
|
-
children,
|
|
71118
|
-
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(Toast, {
|
|
71119
|
-
currentToast
|
|
71120
|
-
}, undefined, false, undefined, this)
|
|
71121
|
-
]
|
|
71122
|
-
}, undefined, true, undefined, this);
|
|
71123
|
-
}
|
|
71124
|
-
function Toast({ currentToast }) {
|
|
71125
|
-
const { width } = useTerminalDimensions();
|
|
71126
|
-
const { colors } = useTheme();
|
|
71127
|
-
if (!currentToast) {
|
|
71128
|
-
return null;
|
|
71129
|
-
}
|
|
71130
|
-
const variantColors = {
|
|
71131
|
-
success: colors.success,
|
|
71132
|
-
error: colors.error,
|
|
71133
|
-
info: colors.info
|
|
71134
|
-
};
|
|
71135
|
-
const borderColor = currentToast.variant ? variantColors[currentToast.variant] : variantColors.info;
|
|
71136
|
-
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
71137
|
-
position: "absolute",
|
|
71138
|
-
justifyContent: "center",
|
|
71139
|
-
alignItems: "flex-start",
|
|
71140
|
-
top: 2,
|
|
71141
|
-
right: 2,
|
|
71142
|
-
width: Math.max(1, Math.min(60, width - 6)),
|
|
71143
|
-
paddingLeft: 2,
|
|
71144
|
-
paddingRight: 2,
|
|
71145
|
-
paddingTop: 1,
|
|
71146
|
-
paddingBottom: 1,
|
|
71147
|
-
backgroundColor: colors.surface,
|
|
71148
|
-
borderColor,
|
|
71149
|
-
border: ["left", "right"],
|
|
71150
|
-
customBorderChars: SplitBorderChars,
|
|
71151
|
-
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
71152
|
-
flexDirection: "column",
|
|
71153
|
-
gap: 1,
|
|
71154
|
-
width: "100%",
|
|
71155
|
-
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
71156
|
-
fg: "#E1E1E1",
|
|
71157
|
-
wrapMode: "word",
|
|
71158
|
-
width: "100%",
|
|
71159
|
-
children: currentToast.message
|
|
71160
|
-
}, undefined, false, undefined, this)
|
|
71161
|
-
}, undefined, false, undefined, this)
|
|
71162
|
-
}, undefined, false, undefined, this);
|
|
71163
|
-
}
|
|
71164
|
-
|
|
71165
|
-
// src/providers/dialog/index.tsx
|
|
71166
|
-
var import_react24 = __toESM(require_react(), 1);
|
|
71167
|
-
|
|
71168
|
-
// src/providers/keyboard-layer/index.tsx
|
|
71169
|
-
var import_react21 = __toESM(require_react(), 1);
|
|
71170
|
-
var KeyboardLayerContext = import_react21.createContext(null);
|
|
71171
|
-
function KeyboardLayerProvider({ children }) {
|
|
71172
|
-
const [stack, setStack] = import_react21.useState(["base"]);
|
|
71173
|
-
const stackRef = import_react21.useRef(stack);
|
|
71174
|
-
stackRef.current = stack;
|
|
71175
|
-
const responders = import_react21.useRef(new Map);
|
|
71176
|
-
const renderer = useRenderer();
|
|
71177
|
-
const push = import_react21.useCallback((id, responder) => {
|
|
71178
|
-
if (responder) {
|
|
71179
|
-
responders.current.set(id, responder);
|
|
71052
|
+
},
|
|
71053
|
+
{
|
|
71054
|
+
name: "Kanagawa Wave",
|
|
71055
|
+
colors: {
|
|
71056
|
+
primary: "#7E9CD8",
|
|
71057
|
+
planMode: "#E6C384",
|
|
71058
|
+
selectMode: "#957FB8",
|
|
71059
|
+
thinking: "#98BB6C",
|
|
71060
|
+
success: "#98BB6C",
|
|
71061
|
+
error: "#E46876",
|
|
71062
|
+
info: "#7FB4CA",
|
|
71063
|
+
background: "#1F1F28",
|
|
71064
|
+
surface: "#2A2A37",
|
|
71065
|
+
dialogSurface: "#363646",
|
|
71066
|
+
thinkingBorder: "#98BB6C",
|
|
71067
|
+
dimSeparator: "#54546D"
|
|
71180
71068
|
}
|
|
71181
|
-
|
|
71182
|
-
|
|
71183
|
-
|
|
71184
|
-
|
|
71185
|
-
|
|
71186
|
-
|
|
71187
|
-
|
|
71188
|
-
|
|
71189
|
-
|
|
71190
|
-
|
|
71191
|
-
|
|
71192
|
-
|
|
71193
|
-
|
|
71194
|
-
|
|
71195
|
-
|
|
71196
|
-
|
|
71197
|
-
responders.current.set(id, responder);
|
|
71198
|
-
} else {
|
|
71199
|
-
responders.current.delete(id);
|
|
71069
|
+
},
|
|
71070
|
+
{
|
|
71071
|
+
name: "Monokai Pro",
|
|
71072
|
+
colors: {
|
|
71073
|
+
primary: "#78DCE8",
|
|
71074
|
+
planMode: "#FFD866",
|
|
71075
|
+
selectMode: "#AB9DF2",
|
|
71076
|
+
thinking: "#A9DC76",
|
|
71077
|
+
success: "#A9DC76",
|
|
71078
|
+
error: "#FF6188",
|
|
71079
|
+
info: "#78DCE8",
|
|
71080
|
+
background: "#2D2A2E",
|
|
71081
|
+
surface: "#36333A",
|
|
71082
|
+
dialogSurface: "#403E41",
|
|
71083
|
+
thinkingBorder: "#A9DC76",
|
|
71084
|
+
dimSeparator: "#727072"
|
|
71200
71085
|
}
|
|
71201
|
-
},
|
|
71202
|
-
|
|
71203
|
-
|
|
71204
|
-
|
|
71205
|
-
|
|
71206
|
-
|
|
71207
|
-
|
|
71208
|
-
|
|
71209
|
-
|
|
71210
|
-
|
|
71211
|
-
|
|
71086
|
+
},
|
|
71087
|
+
{
|
|
71088
|
+
name: "Material Theme",
|
|
71089
|
+
colors: {
|
|
71090
|
+
primary: "#82AAFF",
|
|
71091
|
+
planMode: "#FFCB6B",
|
|
71092
|
+
selectMode: "#C792EA",
|
|
71093
|
+
thinking: "#C3E88D",
|
|
71094
|
+
success: "#C3E88D",
|
|
71095
|
+
error: "#F07178",
|
|
71096
|
+
info: "#89DDFF",
|
|
71097
|
+
background: "#263238",
|
|
71098
|
+
surface: "#2F3B43",
|
|
71099
|
+
dialogSurface: "#37474F",
|
|
71100
|
+
thinkingBorder: "#C3E88D",
|
|
71101
|
+
dimSeparator: "#546E7A"
|
|
71212
71102
|
}
|
|
71213
|
-
|
|
71214
|
-
|
|
71215
|
-
|
|
71216
|
-
|
|
71217
|
-
|
|
71218
|
-
|
|
71219
|
-
|
|
71220
|
-
|
|
71221
|
-
|
|
71222
|
-
|
|
71223
|
-
|
|
71224
|
-
|
|
71225
|
-
|
|
71226
|
-
|
|
71227
|
-
|
|
71228
|
-
|
|
71229
|
-
var import_react23 = __toESM(require_react(), 1);
|
|
71230
|
-
class ErrorBoundary2 extends import_react23.Component {
|
|
71231
|
-
constructor(props) {
|
|
71232
|
-
super(props);
|
|
71233
|
-
this.state = { error: null };
|
|
71234
|
-
}
|
|
71235
|
-
static getDerivedStateFromError(error) {
|
|
71236
|
-
return { error };
|
|
71237
|
-
}
|
|
71238
|
-
componentDidCatch(error, errorInfo) {
|
|
71239
|
-
console.error("[ErrorBoundary] Caught error:", error, errorInfo.componentStack);
|
|
71240
|
-
}
|
|
71241
|
-
render() {
|
|
71242
|
-
if (this.state.error) {
|
|
71243
|
-
console.error("[ErrorBoundary] Rendering fallback for:", this.state.error.message);
|
|
71244
|
-
return this.props.fallback ?? /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
71245
|
-
flexDirection: "column",
|
|
71246
|
-
padding: 1,
|
|
71247
|
-
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
71248
|
-
children: [
|
|
71249
|
-
"Error: ",
|
|
71250
|
-
this.state.error.message
|
|
71251
|
-
]
|
|
71252
|
-
}, undefined, true, undefined, this)
|
|
71253
|
-
}, undefined, false, undefined, this);
|
|
71103
|
+
},
|
|
71104
|
+
{
|
|
71105
|
+
name: "Rose Pine Moon",
|
|
71106
|
+
colors: {
|
|
71107
|
+
primary: "#C4A7E7",
|
|
71108
|
+
planMode: "#F6C177",
|
|
71109
|
+
selectMode: "#9CCFD8",
|
|
71110
|
+
thinking: "#31748F",
|
|
71111
|
+
success: "#9CCFD8",
|
|
71112
|
+
error: "#EB6F92",
|
|
71113
|
+
info: "#C4A7E7",
|
|
71114
|
+
background: "#232136",
|
|
71115
|
+
surface: "#2A273F",
|
|
71116
|
+
dialogSurface: "#393552",
|
|
71117
|
+
thinkingBorder: "#31748F",
|
|
71118
|
+
dimSeparator: "#59546D"
|
|
71254
71119
|
}
|
|
71255
|
-
|
|
71256
|
-
|
|
71257
|
-
|
|
71258
|
-
|
|
71259
|
-
|
|
71260
|
-
|
|
71261
|
-
|
|
71262
|
-
|
|
71263
|
-
|
|
71264
|
-
|
|
71265
|
-
|
|
71266
|
-
|
|
71267
|
-
|
|
71268
|
-
|
|
71269
|
-
|
|
71270
|
-
|
|
71271
|
-
|
|
71272
|
-
|
|
71273
|
-
|
|
71274
|
-
|
|
71275
|
-
|
|
71276
|
-
|
|
71277
|
-
|
|
71278
|
-
|
|
71279
|
-
|
|
71280
|
-
|
|
71281
|
-
|
|
71282
|
-
|
|
71283
|
-
|
|
71284
|
-
|
|
71285
|
-
|
|
71286
|
-
|
|
71287
|
-
|
|
71288
|
-
|
|
71289
|
-
|
|
71290
|
-
|
|
71291
|
-
|
|
71292
|
-
|
|
71293
|
-
|
|
71294
|
-
|
|
71295
|
-
|
|
71296
|
-
|
|
71297
|
-
|
|
71298
|
-
|
|
71299
|
-
|
|
71300
|
-
|
|
71301
|
-
|
|
71302
|
-
|
|
71303
|
-
|
|
71304
|
-
|
|
71305
|
-
|
|
71120
|
+
},
|
|
71121
|
+
{
|
|
71122
|
+
name: "GitHub Dark",
|
|
71123
|
+
colors: {
|
|
71124
|
+
primary: "#58A6FF",
|
|
71125
|
+
planMode: "#E3B341",
|
|
71126
|
+
selectMode: "#A371F7",
|
|
71127
|
+
thinking: "#3FB950",
|
|
71128
|
+
success: "#3FB950",
|
|
71129
|
+
error: "#F85149",
|
|
71130
|
+
info: "#79C0FF",
|
|
71131
|
+
background: "#0D1117",
|
|
71132
|
+
surface: "#161B22",
|
|
71133
|
+
dialogSurface: "#21262D",
|
|
71134
|
+
thinkingBorder: "#3FB950",
|
|
71135
|
+
dimSeparator: "#30363D"
|
|
71136
|
+
}
|
|
71137
|
+
},
|
|
71138
|
+
{
|
|
71139
|
+
name: "SynthWave '84",
|
|
71140
|
+
colors: {
|
|
71141
|
+
primary: "#36F9F6",
|
|
71142
|
+
planMode: "#FFE347",
|
|
71143
|
+
selectMode: "#FF7EDB",
|
|
71144
|
+
thinking: "#72F1B8",
|
|
71145
|
+
success: "#72F1B8",
|
|
71146
|
+
error: "#FE4450",
|
|
71147
|
+
info: "#36F9F6",
|
|
71148
|
+
background: "#262335",
|
|
71149
|
+
surface: "#34294F",
|
|
71150
|
+
dialogSurface: "#433C68",
|
|
71151
|
+
thinkingBorder: "#72F1B8",
|
|
71152
|
+
dimSeparator: "#5B5478"
|
|
71153
|
+
}
|
|
71154
|
+
},
|
|
71155
|
+
{
|
|
71156
|
+
name: "Horizon",
|
|
71157
|
+
colors: {
|
|
71158
|
+
primary: "#26BBD9",
|
|
71159
|
+
planMode: "#FAC29A",
|
|
71160
|
+
selectMode: "#EE64AC",
|
|
71161
|
+
thinking: "#29D398",
|
|
71162
|
+
success: "#29D398",
|
|
71163
|
+
error: "#E95678",
|
|
71164
|
+
info: "#59E3E3",
|
|
71165
|
+
background: "#1C1E26",
|
|
71166
|
+
surface: "#232530",
|
|
71167
|
+
dialogSurface: "#2E303E",
|
|
71168
|
+
thinkingBorder: "#29D398",
|
|
71169
|
+
dimSeparator: "#6C6F93"
|
|
71170
|
+
}
|
|
71171
|
+
},
|
|
71172
|
+
{
|
|
71173
|
+
name: "Arctic Ice",
|
|
71174
|
+
colors: {
|
|
71175
|
+
primary: "#88C0D0",
|
|
71176
|
+
planMode: "#EBCB8B",
|
|
71177
|
+
selectMode: "#81A1C1",
|
|
71178
|
+
thinking: "#A3BE8C",
|
|
71179
|
+
success: "#A3BE8C",
|
|
71180
|
+
error: "#BF616A",
|
|
71181
|
+
info: "#5E81AC",
|
|
71182
|
+
background: "#242933",
|
|
71183
|
+
surface: "#2E3440",
|
|
71184
|
+
dialogSurface: "#3B4252",
|
|
71185
|
+
thinkingBorder: "#A3BE8C",
|
|
71186
|
+
dimSeparator: "#4C566A"
|
|
71187
|
+
}
|
|
71188
|
+
},
|
|
71189
|
+
{
|
|
71190
|
+
name: "Midnight Purple",
|
|
71191
|
+
colors: {
|
|
71192
|
+
primary: "#9D7DFF",
|
|
71193
|
+
planMode: "#F8C555",
|
|
71194
|
+
selectMode: "#B388FF",
|
|
71195
|
+
thinking: "#43D787",
|
|
71196
|
+
success: "#43D787",
|
|
71197
|
+
error: "#FF5D73",
|
|
71198
|
+
info: "#59C8FF",
|
|
71199
|
+
background: "#11111B",
|
|
71200
|
+
surface: "#1B1B2A",
|
|
71201
|
+
dialogSurface: "#25253A",
|
|
71202
|
+
thinkingBorder: "#43D787",
|
|
71203
|
+
dimSeparator: "#47475A"
|
|
71204
|
+
}
|
|
71205
|
+
},
|
|
71206
|
+
{
|
|
71207
|
+
name: "Poimandres",
|
|
71208
|
+
colors: {
|
|
71209
|
+
primary: "#89DDFF",
|
|
71210
|
+
planMode: "#FFE66D",
|
|
71211
|
+
selectMode: "#C792EA",
|
|
71212
|
+
thinking: "#5DE4C7",
|
|
71213
|
+
success: "#5DE4C7",
|
|
71214
|
+
error: "#D0679D",
|
|
71215
|
+
info: "#91B4D5",
|
|
71216
|
+
background: "#1B1E28",
|
|
71217
|
+
surface: "#222635",
|
|
71218
|
+
dialogSurface: "#2A3042",
|
|
71219
|
+
thinkingBorder: "#5DE4C7",
|
|
71220
|
+
dimSeparator: "#4F5B76"
|
|
71221
|
+
}
|
|
71222
|
+
},
|
|
71223
|
+
{
|
|
71224
|
+
name: "Vesper",
|
|
71225
|
+
colors: {
|
|
71226
|
+
primary: "#99FFE4",
|
|
71227
|
+
planMode: "#FFC799",
|
|
71228
|
+
selectMode: "#FCA7EA",
|
|
71229
|
+
thinking: "#A1EFD3",
|
|
71230
|
+
success: "#A1EFD3",
|
|
71231
|
+
error: "#F07178",
|
|
71232
|
+
info: "#8BD5FF",
|
|
71233
|
+
background: "#101010",
|
|
71234
|
+
surface: "#181818",
|
|
71235
|
+
dialogSurface: "#222222",
|
|
71236
|
+
thinkingBorder: "#A1EFD3",
|
|
71237
|
+
dimSeparator: "#3B3B3B"
|
|
71238
|
+
}
|
|
71239
|
+
},
|
|
71240
|
+
{
|
|
71241
|
+
name: "Oxocarbon",
|
|
71242
|
+
colors: {
|
|
71243
|
+
primary: "#78A9FF",
|
|
71244
|
+
planMode: "#FF7EB6",
|
|
71245
|
+
selectMode: "#BE95FF",
|
|
71246
|
+
thinking: "#42BE65",
|
|
71247
|
+
success: "#42BE65",
|
|
71248
|
+
error: "#EE5396",
|
|
71249
|
+
info: "#33B1FF",
|
|
71250
|
+
background: "#161616",
|
|
71251
|
+
surface: "#262626",
|
|
71252
|
+
dialogSurface: "#393939",
|
|
71253
|
+
thinkingBorder: "#42BE65",
|
|
71254
|
+
dimSeparator: "#525252"
|
|
71255
|
+
}
|
|
71256
|
+
},
|
|
71257
|
+
{
|
|
71258
|
+
name: "Flexoki Dark",
|
|
71259
|
+
colors: {
|
|
71260
|
+
primary: "#4385BE",
|
|
71261
|
+
planMode: "#DA702C",
|
|
71262
|
+
selectMode: "#8B7EC8",
|
|
71263
|
+
thinking: "#879A39",
|
|
71264
|
+
success: "#879A39",
|
|
71265
|
+
error: "#D14D41",
|
|
71266
|
+
info: "#3AA99F",
|
|
71267
|
+
background: "#100F0F",
|
|
71268
|
+
surface: "#1C1B1A",
|
|
71269
|
+
dialogSurface: "#282726",
|
|
71270
|
+
thinkingBorder: "#879A39",
|
|
71271
|
+
dimSeparator: "#575653"
|
|
71272
|
+
}
|
|
71273
|
+
},
|
|
71274
|
+
{
|
|
71275
|
+
name: "Dark Plus",
|
|
71276
|
+
colors: {
|
|
71277
|
+
primary: "#569CD6",
|
|
71278
|
+
planMode: "#DCDCAA",
|
|
71279
|
+
selectMode: "#C586C0",
|
|
71280
|
+
thinking: "#6A9955",
|
|
71281
|
+
success: "#6A9955",
|
|
71282
|
+
error: "#F44747",
|
|
71283
|
+
info: "#4FC1FF",
|
|
71284
|
+
background: "#1E1E1E",
|
|
71285
|
+
surface: "#252526",
|
|
71286
|
+
dialogSurface: "#2D2D30",
|
|
71287
|
+
thinkingBorder: "#6A9955",
|
|
71288
|
+
dimSeparator: "#3E3E42"
|
|
71289
|
+
}
|
|
71290
|
+
},
|
|
71291
|
+
{
|
|
71292
|
+
name: "Dark Modern",
|
|
71293
|
+
colors: {
|
|
71294
|
+
primary: "#4FC1FF",
|
|
71295
|
+
planMode: "#E5C07B",
|
|
71296
|
+
selectMode: "#C678DD",
|
|
71297
|
+
thinking: "#7EE787",
|
|
71298
|
+
success: "#7EE787",
|
|
71299
|
+
error: "#FF7B72",
|
|
71300
|
+
info: "#79C0FF",
|
|
71301
|
+
background: "#181818",
|
|
71302
|
+
surface: "#212121",
|
|
71303
|
+
dialogSurface: "#2B2B2B",
|
|
71304
|
+
thinkingBorder: "#7EE787",
|
|
71305
|
+
dimSeparator: "#444444"
|
|
71306
|
+
}
|
|
71307
|
+
},
|
|
71308
|
+
{
|
|
71309
|
+
name: "Dark+ (Default Dark)",
|
|
71310
|
+
colors: {
|
|
71311
|
+
primary: "#569CD6",
|
|
71312
|
+
planMode: "#DCDCAA",
|
|
71313
|
+
selectMode: "#C586C0",
|
|
71314
|
+
thinking: "#6A9955",
|
|
71315
|
+
success: "#6A9955",
|
|
71316
|
+
error: "#F44747",
|
|
71317
|
+
info: "#4FC1FF",
|
|
71318
|
+
background: "#1E1E1E",
|
|
71319
|
+
surface: "#252526",
|
|
71320
|
+
dialogSurface: "#2D2D30",
|
|
71321
|
+
thinkingBorder: "#6A9955",
|
|
71322
|
+
dimSeparator: "#3E3E42"
|
|
71323
|
+
}
|
|
71324
|
+
},
|
|
71325
|
+
{
|
|
71326
|
+
name: "Dark Modern",
|
|
71327
|
+
colors: {
|
|
71328
|
+
primary: "#75BEFF",
|
|
71329
|
+
planMode: "#E5C07B",
|
|
71330
|
+
selectMode: "#D2A8FF",
|
|
71331
|
+
thinking: "#7EE787",
|
|
71332
|
+
success: "#7EE787",
|
|
71333
|
+
error: "#FF7B72",
|
|
71334
|
+
info: "#79C0FF",
|
|
71335
|
+
background: "#181818",
|
|
71336
|
+
surface: "#202020",
|
|
71337
|
+
dialogSurface: "#2A2A2A",
|
|
71338
|
+
thinkingBorder: "#7EE787",
|
|
71339
|
+
dimSeparator: "#3F3F46"
|
|
71340
|
+
}
|
|
71341
|
+
},
|
|
71342
|
+
{
|
|
71343
|
+
name: "High Contrast Dark",
|
|
71344
|
+
colors: {
|
|
71345
|
+
primary: "#3B8EEA",
|
|
71346
|
+
planMode: "#FFCC00",
|
|
71347
|
+
selectMode: "#B180D7",
|
|
71348
|
+
thinking: "#89D185",
|
|
71349
|
+
success: "#89D185",
|
|
71350
|
+
error: "#F14C4C",
|
|
71351
|
+
info: "#75BEFF",
|
|
71352
|
+
background: "#000000",
|
|
71353
|
+
surface: "#0F0F0F",
|
|
71354
|
+
dialogSurface: "#1A1A1A",
|
|
71355
|
+
thinkingBorder: "#89D185",
|
|
71356
|
+
dimSeparator: "#6B6B6B"
|
|
71357
|
+
}
|
|
71358
|
+
},
|
|
71359
|
+
{
|
|
71360
|
+
name: "High Contrast Black",
|
|
71361
|
+
colors: {
|
|
71362
|
+
primary: "#3794FF",
|
|
71363
|
+
planMode: "#FFD700",
|
|
71364
|
+
selectMode: "#C586C0",
|
|
71365
|
+
thinking: "#00FF00",
|
|
71366
|
+
success: "#00FF00",
|
|
71367
|
+
error: "#FF5555",
|
|
71368
|
+
info: "#4FC1FF",
|
|
71369
|
+
background: "#000000",
|
|
71370
|
+
surface: "#111111",
|
|
71371
|
+
dialogSurface: "#1C1C1C",
|
|
71372
|
+
thinkingBorder: "#00FF00",
|
|
71373
|
+
dimSeparator: "#666666"
|
|
71306
71374
|
}
|
|
71307
|
-
});
|
|
71308
|
-
if (!currentDialog) {
|
|
71309
|
-
return null;
|
|
71310
71375
|
}
|
|
71311
|
-
|
|
71312
|
-
|
|
71313
|
-
position: "absolute",
|
|
71314
|
-
left: 0,
|
|
71315
|
-
top: 0,
|
|
71316
|
-
width: dimensions.width,
|
|
71317
|
-
height: dimensions.height,
|
|
71318
|
-
justifyContent: "center",
|
|
71319
|
-
alignItems: "center",
|
|
71320
|
-
backgroundColor: RGBA.fromInts(0, 0, 0, 150),
|
|
71321
|
-
zIndex: 100,
|
|
71322
|
-
onMouseDown: () => close(),
|
|
71323
|
-
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
71324
|
-
width: Math.min(60, dimensions.width - 4),
|
|
71325
|
-
height: "auto",
|
|
71326
|
-
backgroundColor: colors.dialogSurface,
|
|
71327
|
-
paddingX: 4,
|
|
71328
|
-
paddingY: 1,
|
|
71329
|
-
flexDirection: "column",
|
|
71330
|
-
gap: 1,
|
|
71331
|
-
onMouseDown: (e) => e.stopPropagation(),
|
|
71332
|
-
children: [
|
|
71333
|
-
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
71334
|
-
paddingBottom: 1,
|
|
71335
|
-
flexDirection: "row",
|
|
71336
|
-
alignItems: "center",
|
|
71337
|
-
justifyContent: "space-between",
|
|
71338
|
-
children: [
|
|
71339
|
-
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
71340
|
-
attributes: TextAttributes.BOLD,
|
|
71341
|
-
children: title
|
|
71342
|
-
}, undefined, false, undefined, this),
|
|
71343
|
-
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
71344
|
-
attributes: TextAttributes.DIM,
|
|
71345
|
-
onMouseDown: () => close(),
|
|
71346
|
-
children: "esc"
|
|
71347
|
-
}, undefined, false, undefined, this)
|
|
71348
|
-
]
|
|
71349
|
-
}, undefined, true, undefined, this),
|
|
71350
|
-
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
71351
|
-
flexGrow: 1,
|
|
71352
|
-
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(ErrorBoundary2, {
|
|
71353
|
-
children
|
|
71354
|
-
}, undefined, false, undefined, this)
|
|
71355
|
-
}, undefined, false, undefined, this)
|
|
71356
|
-
]
|
|
71357
|
-
}, undefined, true, undefined, this)
|
|
71358
|
-
}, undefined, false, undefined, this);
|
|
71359
|
-
}
|
|
71360
|
-
|
|
71361
|
-
// src/layouts/themed-root.tsx
|
|
71362
|
-
function ThemedRoot({ children }) {
|
|
71363
|
-
const { colors } = useTheme();
|
|
71364
|
-
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
71365
|
-
backgroundColor: colors.background,
|
|
71366
|
-
width: "100%",
|
|
71367
|
-
height: "100%",
|
|
71368
|
-
flexGrow: 1,
|
|
71369
|
-
children
|
|
71370
|
-
}, undefined, false, undefined, this);
|
|
71371
|
-
}
|
|
71376
|
+
];
|
|
71377
|
+
var DEFAULT_THEME = THEMES.find((t2) => t2.name === "Nightfox");
|
|
71372
71378
|
|
|
71373
|
-
// src/
|
|
71374
|
-
|
|
71379
|
+
// src/lib/config.ts
|
|
71380
|
+
import { mkdirSync, readFileSync, writeFileSync as writeFileSync2 } from "fs";
|
|
71381
|
+
import { homedir } from "os";
|
|
71382
|
+
import { join as join2 } from "path";
|
|
71375
71383
|
|
|
71376
71384
|
// ../../node_modules/zod/v4/classic/external.js
|
|
71377
71385
|
var exports_external = {};
|
|
@@ -85685,6 +85693,12 @@ var toolInputSchemas = {
|
|
|
85685
85693
|
command: exports_external.string().describe("Shell command to run"),
|
|
85686
85694
|
description: exports_external.string().optional().describe("Short description of the command"),
|
|
85687
85695
|
timeout: exports_external.number().optional().describe("Timeout in milliseconds")
|
|
85696
|
+
}),
|
|
85697
|
+
deleteFile: exports_external.object({
|
|
85698
|
+
path: exports_external.string().describe("Relative path to the file to delete")
|
|
85699
|
+
}),
|
|
85700
|
+
webSearch: exports_external.object({
|
|
85701
|
+
query: exports_external.string().describe("Search query for web search")
|
|
85688
85702
|
})
|
|
85689
85703
|
};
|
|
85690
85704
|
// node_modules/ai/node_modules/@ai-sdk/provider/dist/index.js
|
|
@@ -93393,10 +93407,18 @@ var readOnlyToolContracts = {
|
|
|
93393
93407
|
grep: tool({
|
|
93394
93408
|
description: "Search file contents with a regular expression under the current project directory.",
|
|
93395
93409
|
inputSchema: toolInputSchemas.grep
|
|
93410
|
+
}),
|
|
93411
|
+
webSearch: tool({
|
|
93412
|
+
description: "Search the web for up-to-date information on any topic.",
|
|
93413
|
+
inputSchema: toolInputSchemas.webSearch
|
|
93396
93414
|
})
|
|
93397
93415
|
};
|
|
93398
93416
|
var buildToolContracts = {
|
|
93399
93417
|
...readOnlyToolContracts,
|
|
93418
|
+
deleteFile: tool({
|
|
93419
|
+
description: "Delete a file under the current project directory.",
|
|
93420
|
+
inputSchema: toolInputSchemas.deleteFile
|
|
93421
|
+
}),
|
|
93400
93422
|
writeFile: tool({
|
|
93401
93423
|
description: "Create or overwrite a file under the current project directory.",
|
|
93402
93424
|
inputSchema: toolInputSchemas.writeFile
|
|
@@ -93413,7 +93435,7 @@ var buildToolContracts = {
|
|
|
93413
93435
|
// src/lib/shared/models.ts
|
|
93414
93436
|
var SUPPORTED_CHAT_MODELS = [
|
|
93415
93437
|
{
|
|
93416
|
-
id: "claude-sonnet-
|
|
93438
|
+
id: "claude-sonnet-5",
|
|
93417
93439
|
provider: "anthropic",
|
|
93418
93440
|
pricing: {
|
|
93419
93441
|
inputUsdPerMillionTokens: 3,
|
|
@@ -93421,7 +93443,7 @@ var SUPPORTED_CHAT_MODELS = [
|
|
|
93421
93443
|
}
|
|
93422
93444
|
},
|
|
93423
93445
|
{
|
|
93424
|
-
id: "claude-
|
|
93446
|
+
id: "claude-haiku-4-5",
|
|
93425
93447
|
provider: "anthropic",
|
|
93426
93448
|
pricing: {
|
|
93427
93449
|
inputUsdPerMillionTokens: 1,
|
|
@@ -93429,7 +93451,7 @@ var SUPPORTED_CHAT_MODELS = [
|
|
|
93429
93451
|
}
|
|
93430
93452
|
},
|
|
93431
93453
|
{
|
|
93432
|
-
id: "claude-opus-4-
|
|
93454
|
+
id: "claude-opus-4-8",
|
|
93433
93455
|
provider: "anthropic",
|
|
93434
93456
|
pricing: {
|
|
93435
93457
|
inputUsdPerMillionTokens: 5,
|
|
@@ -93437,7 +93459,7 @@ var SUPPORTED_CHAT_MODELS = [
|
|
|
93437
93459
|
}
|
|
93438
93460
|
},
|
|
93439
93461
|
{
|
|
93440
|
-
id: "gpt-
|
|
93462
|
+
id: "gpt-5.5",
|
|
93441
93463
|
provider: "openai",
|
|
93442
93464
|
pricing: {
|
|
93443
93465
|
inputUsdPerMillionTokens: 2.5,
|
|
@@ -93445,7 +93467,7 @@ var SUPPORTED_CHAT_MODELS = [
|
|
|
93445
93467
|
}
|
|
93446
93468
|
},
|
|
93447
93469
|
{
|
|
93448
|
-
id: "gpt-4
|
|
93470
|
+
id: "gpt-5.4-mini",
|
|
93449
93471
|
provider: "openai",
|
|
93450
93472
|
pricing: {
|
|
93451
93473
|
inputUsdPerMillionTokens: 0.75,
|
|
@@ -93453,7 +93475,7 @@ var SUPPORTED_CHAT_MODELS = [
|
|
|
93453
93475
|
}
|
|
93454
93476
|
},
|
|
93455
93477
|
{
|
|
93456
|
-
id: "gpt-4
|
|
93478
|
+
id: "gpt-5.4-nano",
|
|
93457
93479
|
provider: "openai",
|
|
93458
93480
|
pricing: {
|
|
93459
93481
|
inputUsdPerMillionTokens: 0.2,
|
|
@@ -93461,19 +93483,19 @@ var SUPPORTED_CHAT_MODELS = [
|
|
|
93461
93483
|
}
|
|
93462
93484
|
},
|
|
93463
93485
|
{
|
|
93464
|
-
id: "
|
|
93486
|
+
id: "cohere/north-mini-code:free",
|
|
93465
93487
|
provider: "openrouter",
|
|
93466
93488
|
pricing: {
|
|
93467
|
-
inputUsdPerMillionTokens: 0
|
|
93468
|
-
outputUsdPerMillionTokens:
|
|
93489
|
+
inputUsdPerMillionTokens: 0,
|
|
93490
|
+
outputUsdPerMillionTokens: 0
|
|
93469
93491
|
}
|
|
93470
93492
|
},
|
|
93471
93493
|
{
|
|
93472
|
-
id: "
|
|
93473
|
-
provider: "
|
|
93494
|
+
id: "deepseek/deepseek-chat-v3",
|
|
93495
|
+
provider: "openrouter",
|
|
93474
93496
|
pricing: {
|
|
93475
|
-
inputUsdPerMillionTokens: 0.
|
|
93476
|
-
outputUsdPerMillionTokens:
|
|
93497
|
+
inputUsdPerMillionTokens: 0.27,
|
|
93498
|
+
outputUsdPerMillionTokens: 1.1
|
|
93477
93499
|
}
|
|
93478
93500
|
},
|
|
93479
93501
|
{
|
|
@@ -93485,11 +93507,67 @@ var SUPPORTED_CHAT_MODELS = [
|
|
|
93485
93507
|
}
|
|
93486
93508
|
},
|
|
93487
93509
|
{
|
|
93488
|
-
id: "deepseek/deepseek-
|
|
93510
|
+
id: "deepseek/deepseek-v3.2",
|
|
93489
93511
|
provider: "openrouter",
|
|
93490
93512
|
pricing: {
|
|
93491
|
-
inputUsdPerMillionTokens: 0.
|
|
93492
|
-
outputUsdPerMillionTokens:
|
|
93513
|
+
inputUsdPerMillionTokens: 0.2288,
|
|
93514
|
+
outputUsdPerMillionTokens: 0.3432
|
|
93515
|
+
}
|
|
93516
|
+
},
|
|
93517
|
+
{
|
|
93518
|
+
id: "deepseek/deepseek-v4-flash",
|
|
93519
|
+
provider: "openrouter",
|
|
93520
|
+
pricing: {
|
|
93521
|
+
inputUsdPerMillionTokens: 0.1,
|
|
93522
|
+
outputUsdPerMillionTokens: 0.2
|
|
93523
|
+
}
|
|
93524
|
+
},
|
|
93525
|
+
{
|
|
93526
|
+
id: "deepseek/deepseek-v4-pro",
|
|
93527
|
+
provider: "openrouter",
|
|
93528
|
+
pricing: {
|
|
93529
|
+
inputUsdPerMillionTokens: 0.435,
|
|
93530
|
+
outputUsdPerMillionTokens: 0.87
|
|
93531
|
+
}
|
|
93532
|
+
},
|
|
93533
|
+
{
|
|
93534
|
+
id: "nvidia/nemotron-3-super-120b-a12b:free",
|
|
93535
|
+
provider: "openrouter",
|
|
93536
|
+
pricing: {
|
|
93537
|
+
inputUsdPerMillionTokens: 0,
|
|
93538
|
+
outputUsdPerMillionTokens: 0
|
|
93539
|
+
}
|
|
93540
|
+
},
|
|
93541
|
+
{
|
|
93542
|
+
id: "nvidia/nemotron-3-ultra-550b-a55b:free",
|
|
93543
|
+
provider: "openrouter",
|
|
93544
|
+
pricing: {
|
|
93545
|
+
inputUsdPerMillionTokens: 0,
|
|
93546
|
+
outputUsdPerMillionTokens: 0
|
|
93547
|
+
}
|
|
93548
|
+
},
|
|
93549
|
+
{
|
|
93550
|
+
id: "poolside/laguna-m.1:free",
|
|
93551
|
+
provider: "openrouter",
|
|
93552
|
+
pricing: {
|
|
93553
|
+
inputUsdPerMillionTokens: 0,
|
|
93554
|
+
outputUsdPerMillionTokens: 0
|
|
93555
|
+
}
|
|
93556
|
+
},
|
|
93557
|
+
{
|
|
93558
|
+
id: "qwen/qwen3-coder",
|
|
93559
|
+
provider: "openrouter",
|
|
93560
|
+
pricing: {
|
|
93561
|
+
inputUsdPerMillionTokens: 0.3,
|
|
93562
|
+
outputUsdPerMillionTokens: 1.2
|
|
93563
|
+
}
|
|
93564
|
+
},
|
|
93565
|
+
{
|
|
93566
|
+
id: "qwen/qwen3-coder-next",
|
|
93567
|
+
provider: "openrouter",
|
|
93568
|
+
pricing: {
|
|
93569
|
+
inputUsdPerMillionTokens: 0.11,
|
|
93570
|
+
outputUsdPerMillionTokens: 0.8
|
|
93493
93571
|
}
|
|
93494
93572
|
},
|
|
93495
93573
|
{
|
|
@@ -93500,6 +93578,22 @@ var SUPPORTED_CHAT_MODELS = [
|
|
|
93500
93578
|
outputUsdPerMillionTokens: 0
|
|
93501
93579
|
}
|
|
93502
93580
|
},
|
|
93581
|
+
{
|
|
93582
|
+
id: "gemini-3-flash-lite",
|
|
93583
|
+
provider: "google",
|
|
93584
|
+
pricing: {
|
|
93585
|
+
inputUsdPerMillionTokens: 0.25,
|
|
93586
|
+
outputUsdPerMillionTokens: 1.5
|
|
93587
|
+
}
|
|
93588
|
+
},
|
|
93589
|
+
{
|
|
93590
|
+
id: "gemini-3-flash-preview",
|
|
93591
|
+
provider: "google",
|
|
93592
|
+
pricing: {
|
|
93593
|
+
inputUsdPerMillionTokens: 0.5,
|
|
93594
|
+
outputUsdPerMillionTokens: 3
|
|
93595
|
+
}
|
|
93596
|
+
},
|
|
93503
93597
|
{
|
|
93504
93598
|
id: "llama-3.3-70b-versatile",
|
|
93505
93599
|
provider: "groq",
|
|
@@ -93547,7 +93641,7 @@ function findSupportedChatModel(modelId) {
|
|
|
93547
93641
|
function isFreeModel(model) {
|
|
93548
93642
|
return model.pricing.inputUsdPerMillionTokens === 0 && model.pricing.outputUsdPerMillionTokens === 0;
|
|
93549
93643
|
}
|
|
93550
|
-
var DEFAULT_CHAT_MODEL_ID = "
|
|
93644
|
+
var DEFAULT_CHAT_MODEL_ID = "deepseek/deepseek-v4-flash";
|
|
93551
93645
|
// src/lib/shared/domains.ts
|
|
93552
93646
|
var DOMAINS = [
|
|
93553
93647
|
{
|
|
@@ -93565,7 +93659,357 @@ function findDomain(id) {
|
|
|
93565
93659
|
return DOMAINS.find((d2) => d2.id === id);
|
|
93566
93660
|
}
|
|
93567
93661
|
var DEFAULT_DOMAIN_ID = "coding";
|
|
93662
|
+
// src/lib/config.ts
|
|
93663
|
+
var CONFIG_DIR = join2(homedir(), ".lupacode");
|
|
93664
|
+
var CONFIG_PATH = join2(CONFIG_DIR, "preferences.json");
|
|
93665
|
+
var DEFAULTS = {
|
|
93666
|
+
themeName: "Nightfox",
|
|
93667
|
+
mode: Mode.BUILD,
|
|
93668
|
+
model: DEFAULT_CHAT_MODEL_ID,
|
|
93669
|
+
domain: DEFAULT_DOMAIN_ID
|
|
93670
|
+
};
|
|
93671
|
+
function ensureDir() {
|
|
93672
|
+
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
93673
|
+
}
|
|
93674
|
+
function readPreferences() {
|
|
93675
|
+
try {
|
|
93676
|
+
return JSON.parse(readFileSync(CONFIG_PATH, "utf8"));
|
|
93677
|
+
} catch {
|
|
93678
|
+
return {};
|
|
93679
|
+
}
|
|
93680
|
+
}
|
|
93681
|
+
function writePreferences(prefs) {
|
|
93682
|
+
try {
|
|
93683
|
+
const current = readPreferences();
|
|
93684
|
+
ensureDir();
|
|
93685
|
+
writeFileSync2(CONFIG_PATH, JSON.stringify({ ...current, ...prefs }, null, 2), "utf8");
|
|
93686
|
+
} catch {}
|
|
93687
|
+
}
|
|
93688
|
+
|
|
93689
|
+
// ../../node_modules/@opentui/react/jsx-dev-runtime.js
|
|
93690
|
+
var import_jsx_dev_runtime2 = __toESM(require_jsx_dev_runtime(), 1);
|
|
93691
|
+
|
|
93692
|
+
// src/providers/theme/index.tsx
|
|
93693
|
+
function getInitialTheme() {
|
|
93694
|
+
const prefs = readPreferences();
|
|
93695
|
+
const savedTheme = typeof prefs.themeName === "string" ? THEMES.find((t2) => t2.name === prefs.themeName) : undefined;
|
|
93696
|
+
return savedTheme ?? DEFAULT_THEME;
|
|
93697
|
+
}
|
|
93698
|
+
function persistTheme(theme) {
|
|
93699
|
+
writePreferences({ themeName: theme.name });
|
|
93700
|
+
}
|
|
93701
|
+
var ThemeContext = import_react18.createContext(null);
|
|
93702
|
+
function useTheme() {
|
|
93703
|
+
const value = import_react18.useContext(ThemeContext);
|
|
93704
|
+
if (!value) {
|
|
93705
|
+
throw new Error("useTheme must be used within a ThemeProvider");
|
|
93706
|
+
}
|
|
93707
|
+
return value;
|
|
93708
|
+
}
|
|
93709
|
+
function ThemeProvider({ children }) {
|
|
93710
|
+
const [currentTheme, setCurrentTheme] = import_react18.useState(getInitialTheme);
|
|
93711
|
+
const setTheme = import_react18.useCallback((theme) => {
|
|
93712
|
+
setCurrentTheme(theme);
|
|
93713
|
+
persistTheme(theme);
|
|
93714
|
+
}, []);
|
|
93715
|
+
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(ThemeContext.Provider, {
|
|
93716
|
+
value: { colors: currentTheme.colors, currentTheme, setTheme },
|
|
93717
|
+
children
|
|
93718
|
+
}, undefined, false, undefined, this);
|
|
93719
|
+
}
|
|
93720
|
+
|
|
93721
|
+
// src/providers/toast/index.tsx
|
|
93722
|
+
var ToastContext = import_react19.createContext(null);
|
|
93723
|
+
function useToast() {
|
|
93724
|
+
const value = import_react19.useContext(ToastContext);
|
|
93725
|
+
if (!value) {
|
|
93726
|
+
throw new Error("useToast must be used within a ToastProvider");
|
|
93727
|
+
}
|
|
93728
|
+
return value;
|
|
93729
|
+
}
|
|
93730
|
+
function ToastProvider({ children }) {
|
|
93731
|
+
const [currentToast, setCurrentToast] = import_react19.useState(null);
|
|
93732
|
+
const timeoutHandleRef = import_react19.useRef(null);
|
|
93733
|
+
const clearCurrentTimeout = import_react19.useCallback(() => {
|
|
93734
|
+
if (timeoutHandleRef.current) {
|
|
93735
|
+
clearTimeout(timeoutHandleRef.current);
|
|
93736
|
+
timeoutHandleRef.current = null;
|
|
93737
|
+
}
|
|
93738
|
+
}, []);
|
|
93739
|
+
const show = import_react19.useCallback((options) => {
|
|
93740
|
+
const duration3 = options.duration ?? DEFAULT_DURATION;
|
|
93741
|
+
clearCurrentTimeout();
|
|
93742
|
+
setCurrentToast({
|
|
93743
|
+
variant: options.variant ?? "info",
|
|
93744
|
+
...options,
|
|
93745
|
+
duration: duration3
|
|
93746
|
+
});
|
|
93747
|
+
timeoutHandleRef.current = setTimeout(() => {
|
|
93748
|
+
setCurrentToast(null);
|
|
93749
|
+
}, duration3).unref();
|
|
93750
|
+
}, [clearCurrentTimeout]);
|
|
93751
|
+
const value = import_react19.useMemo(() => ({ show }), [show]);
|
|
93752
|
+
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(ToastContext.Provider, {
|
|
93753
|
+
value,
|
|
93754
|
+
children: [
|
|
93755
|
+
children,
|
|
93756
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(Toast, {
|
|
93757
|
+
currentToast
|
|
93758
|
+
}, undefined, false, undefined, this)
|
|
93759
|
+
]
|
|
93760
|
+
}, undefined, true, undefined, this);
|
|
93761
|
+
}
|
|
93762
|
+
function Toast({ currentToast }) {
|
|
93763
|
+
const { width } = useTerminalDimensions();
|
|
93764
|
+
const { colors } = useTheme();
|
|
93765
|
+
if (!currentToast) {
|
|
93766
|
+
return null;
|
|
93767
|
+
}
|
|
93768
|
+
const variantColors = {
|
|
93769
|
+
success: colors.success,
|
|
93770
|
+
error: colors.error,
|
|
93771
|
+
info: colors.info
|
|
93772
|
+
};
|
|
93773
|
+
const borderColor = currentToast.variant ? variantColors[currentToast.variant] : variantColors.info;
|
|
93774
|
+
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
93775
|
+
position: "absolute",
|
|
93776
|
+
justifyContent: "center",
|
|
93777
|
+
alignItems: "flex-start",
|
|
93778
|
+
top: 2,
|
|
93779
|
+
right: 2,
|
|
93780
|
+
width: Math.max(1, Math.min(60, width - 6)),
|
|
93781
|
+
paddingLeft: 2,
|
|
93782
|
+
paddingRight: 2,
|
|
93783
|
+
paddingTop: 1,
|
|
93784
|
+
paddingBottom: 1,
|
|
93785
|
+
backgroundColor: colors.surface,
|
|
93786
|
+
borderColor,
|
|
93787
|
+
border: ["left", "right"],
|
|
93788
|
+
customBorderChars: SplitBorderChars,
|
|
93789
|
+
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
93790
|
+
flexDirection: "column",
|
|
93791
|
+
gap: 1,
|
|
93792
|
+
width: "100%",
|
|
93793
|
+
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
93794
|
+
fg: "#E1E1E1",
|
|
93795
|
+
wrapMode: "word",
|
|
93796
|
+
width: "100%",
|
|
93797
|
+
children: currentToast.message
|
|
93798
|
+
}, undefined, false, undefined, this)
|
|
93799
|
+
}, undefined, false, undefined, this)
|
|
93800
|
+
}, undefined, false, undefined, this);
|
|
93801
|
+
}
|
|
93802
|
+
|
|
93803
|
+
// src/providers/dialog/index.tsx
|
|
93804
|
+
var import_react24 = __toESM(require_react(), 1);
|
|
93805
|
+
|
|
93806
|
+
// src/providers/keyboard-layer/index.tsx
|
|
93807
|
+
var import_react21 = __toESM(require_react(), 1);
|
|
93808
|
+
var KeyboardLayerContext = import_react21.createContext(null);
|
|
93809
|
+
function KeyboardLayerProvider({ children }) {
|
|
93810
|
+
const [stack, setStack] = import_react21.useState(["base"]);
|
|
93811
|
+
const stackRef = import_react21.useRef(stack);
|
|
93812
|
+
stackRef.current = stack;
|
|
93813
|
+
const responders = import_react21.useRef(new Map);
|
|
93814
|
+
const renderer = useRenderer();
|
|
93815
|
+
const push = import_react21.useCallback((id, responder) => {
|
|
93816
|
+
if (responder) {
|
|
93817
|
+
responders.current.set(id, responder);
|
|
93818
|
+
}
|
|
93819
|
+
setStack((prev) => [...prev, id]);
|
|
93820
|
+
}, []);
|
|
93821
|
+
const pop = import_react21.useCallback((id) => {
|
|
93822
|
+
setStack((prev) => {
|
|
93823
|
+
const idx = prev.lastIndexOf(id);
|
|
93824
|
+
if (idx === -1)
|
|
93825
|
+
return prev;
|
|
93826
|
+
if (prev.indexOf(id) === idx) {
|
|
93827
|
+
responders.current.delete(id);
|
|
93828
|
+
}
|
|
93829
|
+
return prev.slice(0, idx);
|
|
93830
|
+
});
|
|
93831
|
+
}, []);
|
|
93832
|
+
const isTopLayer = import_react21.useCallback((id) => {
|
|
93833
|
+
return stack.length === 0 || stack[stack.length - 1] === id;
|
|
93834
|
+
}, [stack]);
|
|
93835
|
+
const setResponder = import_react21.useCallback((id, responder) => {
|
|
93836
|
+
if (responder) {
|
|
93837
|
+
responders.current.set(id, responder);
|
|
93838
|
+
} else {
|
|
93839
|
+
responders.current.delete(id);
|
|
93840
|
+
}
|
|
93841
|
+
}, []);
|
|
93842
|
+
useKeyboard((key) => {
|
|
93843
|
+
if (!key.ctrl || key.name !== "c")
|
|
93844
|
+
return;
|
|
93845
|
+
const currentStack = stackRef.current;
|
|
93846
|
+
for (let i = currentStack.length - 1;i >= 0; i--) {
|
|
93847
|
+
const layerId = currentStack[i];
|
|
93848
|
+
const responder = responders.current.get(layerId);
|
|
93849
|
+
if (responder && responder()) {
|
|
93850
|
+
return;
|
|
93851
|
+
}
|
|
93852
|
+
}
|
|
93853
|
+
renderer.destroy();
|
|
93854
|
+
});
|
|
93855
|
+
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(KeyboardLayerContext.Provider, {
|
|
93856
|
+
value: { push, pop, isTopLayer, setResponder },
|
|
93857
|
+
children
|
|
93858
|
+
}, undefined, false, undefined, this);
|
|
93859
|
+
}
|
|
93860
|
+
function useKeyboardLayer() {
|
|
93861
|
+
const context = import_react21.useContext(KeyboardLayerContext);
|
|
93862
|
+
if (!context) {
|
|
93863
|
+
throw new Error("useKeyboardLayer must be used within a KeyboardLayerProvider");
|
|
93864
|
+
}
|
|
93865
|
+
return context;
|
|
93866
|
+
}
|
|
93867
|
+
|
|
93868
|
+
// src/components/error-boundary.tsx
|
|
93869
|
+
var import_react23 = __toESM(require_react(), 1);
|
|
93870
|
+
class ErrorBoundary2 extends import_react23.Component {
|
|
93871
|
+
constructor(props) {
|
|
93872
|
+
super(props);
|
|
93873
|
+
this.state = { error: null };
|
|
93874
|
+
}
|
|
93875
|
+
static getDerivedStateFromError(error51) {
|
|
93876
|
+
return { error: error51 };
|
|
93877
|
+
}
|
|
93878
|
+
componentDidCatch(error51, errorInfo) {
|
|
93879
|
+
console.error("[ErrorBoundary] Caught error:", error51, errorInfo.componentStack);
|
|
93880
|
+
}
|
|
93881
|
+
render() {
|
|
93882
|
+
if (this.state.error) {
|
|
93883
|
+
console.error("[ErrorBoundary] Rendering fallback for:", this.state.error.message);
|
|
93884
|
+
return this.props.fallback ?? /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
93885
|
+
flexDirection: "column",
|
|
93886
|
+
padding: 1,
|
|
93887
|
+
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
93888
|
+
children: [
|
|
93889
|
+
"Error: ",
|
|
93890
|
+
this.state.error.message
|
|
93891
|
+
]
|
|
93892
|
+
}, undefined, true, undefined, this)
|
|
93893
|
+
}, undefined, false, undefined, this);
|
|
93894
|
+
}
|
|
93895
|
+
return this.props.children;
|
|
93896
|
+
}
|
|
93897
|
+
}
|
|
93898
|
+
|
|
93899
|
+
// src/providers/dialog/index.tsx
|
|
93900
|
+
var DialogContext = import_react24.createContext(null);
|
|
93901
|
+
function useDialog() {
|
|
93902
|
+
const value = import_react24.useContext(DialogContext);
|
|
93903
|
+
if (!value) {
|
|
93904
|
+
throw new Error("useDialog must be used within a DialogProvider");
|
|
93905
|
+
}
|
|
93906
|
+
return value;
|
|
93907
|
+
}
|
|
93908
|
+
function DialogProvider({ children }) {
|
|
93909
|
+
const [dialogStack, setDialogStack] = import_react24.useState([]);
|
|
93910
|
+
const { push, pop } = useKeyboardLayer();
|
|
93911
|
+
const close = import_react24.useCallback(() => {
|
|
93912
|
+
setDialogStack((prev) => prev.slice(0, -1));
|
|
93913
|
+
pop("dialog");
|
|
93914
|
+
}, [pop]);
|
|
93915
|
+
const open = import_react24.useCallback((config2) => {
|
|
93916
|
+
setDialogStack((prev) => [...prev, config2]);
|
|
93917
|
+
push("dialog", () => {
|
|
93918
|
+
close();
|
|
93919
|
+
return true;
|
|
93920
|
+
});
|
|
93921
|
+
}, [push, close]);
|
|
93922
|
+
const value = {
|
|
93923
|
+
open,
|
|
93924
|
+
close
|
|
93925
|
+
};
|
|
93926
|
+
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(DialogContext.Provider, {
|
|
93927
|
+
value,
|
|
93928
|
+
children: [
|
|
93929
|
+
children,
|
|
93930
|
+
dialogStack.map((config2, i) => /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(Dialog, {
|
|
93931
|
+
config: config2,
|
|
93932
|
+
close: i === dialogStack.length - 1 ? close : undefined,
|
|
93933
|
+
isBack: i < dialogStack.length - 1
|
|
93934
|
+
}, `dialog-${i}`, false, undefined, this))
|
|
93935
|
+
]
|
|
93936
|
+
}, undefined, true, undefined, this);
|
|
93937
|
+
}
|
|
93938
|
+
function Dialog({ config: config2, close, isBack = false }) {
|
|
93939
|
+
const { isTopLayer } = useKeyboardLayer();
|
|
93940
|
+
const dimensions = useTerminalDimensions();
|
|
93941
|
+
const { colors } = useTheme();
|
|
93942
|
+
useKeyboard((key) => {
|
|
93943
|
+
if (!close || !isTopLayer("dialog"))
|
|
93944
|
+
return;
|
|
93945
|
+
if (key.name === "escape") {
|
|
93946
|
+
close();
|
|
93947
|
+
}
|
|
93948
|
+
});
|
|
93949
|
+
const { title, children } = config2;
|
|
93950
|
+
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
93951
|
+
position: "absolute",
|
|
93952
|
+
left: 0,
|
|
93953
|
+
top: 0,
|
|
93954
|
+
width: dimensions.width,
|
|
93955
|
+
height: dimensions.height,
|
|
93956
|
+
justifyContent: "center",
|
|
93957
|
+
alignItems: "center",
|
|
93958
|
+
backgroundColor: RGBA.fromInts(0, 0, 0, 150),
|
|
93959
|
+
zIndex: 100,
|
|
93960
|
+
onMouseDown: close,
|
|
93961
|
+
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
93962
|
+
width: Math.min(60, dimensions.width - 4),
|
|
93963
|
+
height: "auto",
|
|
93964
|
+
backgroundColor: colors.dialogSurface,
|
|
93965
|
+
paddingX: 4,
|
|
93966
|
+
paddingY: 1,
|
|
93967
|
+
flexDirection: "column",
|
|
93968
|
+
gap: 1,
|
|
93969
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
93970
|
+
children: [
|
|
93971
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
93972
|
+
paddingBottom: 1,
|
|
93973
|
+
flexDirection: "row",
|
|
93974
|
+
alignItems: "center",
|
|
93975
|
+
justifyContent: "space-between",
|
|
93976
|
+
children: [
|
|
93977
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
93978
|
+
attributes: TextAttributes.BOLD,
|
|
93979
|
+
children: title
|
|
93980
|
+
}, undefined, false, undefined, this),
|
|
93981
|
+
close && /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
93982
|
+
attributes: TextAttributes.DIM,
|
|
93983
|
+
onMouseDown: close,
|
|
93984
|
+
children: isBack ? "back (esc)" : "esc"
|
|
93985
|
+
}, undefined, false, undefined, this)
|
|
93986
|
+
]
|
|
93987
|
+
}, undefined, true, undefined, this),
|
|
93988
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
93989
|
+
flexGrow: 1,
|
|
93990
|
+
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(ErrorBoundary2, {
|
|
93991
|
+
children
|
|
93992
|
+
}, undefined, false, undefined, this)
|
|
93993
|
+
}, undefined, false, undefined, this)
|
|
93994
|
+
]
|
|
93995
|
+
}, undefined, true, undefined, this)
|
|
93996
|
+
}, undefined, false, undefined, this);
|
|
93997
|
+
}
|
|
93998
|
+
|
|
93999
|
+
// src/layouts/themed-root.tsx
|
|
94000
|
+
function ThemedRoot({ children }) {
|
|
94001
|
+
const { colors } = useTheme();
|
|
94002
|
+
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
94003
|
+
backgroundColor: colors.background,
|
|
94004
|
+
width: "100%",
|
|
94005
|
+
height: "100%",
|
|
94006
|
+
flexGrow: 1,
|
|
94007
|
+
children
|
|
94008
|
+
}, undefined, false, undefined, this);
|
|
94009
|
+
}
|
|
94010
|
+
|
|
93568
94011
|
// src/providers/prompt-config/index.tsx
|
|
94012
|
+
var import_react26 = __toESM(require_react(), 1);
|
|
93569
94013
|
var PromptConfigContext = import_react26.createContext(null);
|
|
93570
94014
|
function usePromptConfig() {
|
|
93571
94015
|
const value = import_react26.useContext(PromptConfigContext);
|
|
@@ -93574,12 +94018,32 @@ function usePromptConfig() {
|
|
|
93574
94018
|
}
|
|
93575
94019
|
return value;
|
|
93576
94020
|
}
|
|
94021
|
+
function getInitial(key, fallback) {
|
|
94022
|
+
const prefs = readPreferences();
|
|
94023
|
+
return prefs[key] !== undefined ? prefs[key] : fallback;
|
|
94024
|
+
}
|
|
93577
94025
|
function PromptConfigProvider({ children }) {
|
|
93578
|
-
const [mode,
|
|
93579
|
-
const [model,
|
|
93580
|
-
const [domain2,
|
|
94026
|
+
const [mode, setModeState] = import_react26.useState(() => getInitial("mode", Mode.BUILD));
|
|
94027
|
+
const [model, setModelState] = import_react26.useState(() => getInitial("model", DEFAULT_CHAT_MODEL_ID));
|
|
94028
|
+
const [domain2, setDomainState] = import_react26.useState(() => getInitial("domain", DEFAULT_DOMAIN_ID));
|
|
94029
|
+
const setMode = import_react26.useCallback((m2) => {
|
|
94030
|
+
setModeState(m2);
|
|
94031
|
+
writePreferences({ mode: m2 });
|
|
94032
|
+
}, []);
|
|
94033
|
+
const setModel = import_react26.useCallback((m2) => {
|
|
94034
|
+
setModelState(m2);
|
|
94035
|
+
writePreferences({ model: m2 });
|
|
94036
|
+
}, []);
|
|
94037
|
+
const setDomain = import_react26.useCallback((d2) => {
|
|
94038
|
+
setDomainState(d2);
|
|
94039
|
+
writePreferences({ domain: d2 });
|
|
94040
|
+
}, []);
|
|
93581
94041
|
const toggleMode = import_react26.useCallback(() => {
|
|
93582
|
-
|
|
94042
|
+
setModeState((m2) => {
|
|
94043
|
+
const next = m2 === Mode.BUILD ? Mode.PLAN : Mode.BUILD;
|
|
94044
|
+
writePreferences({ mode: next });
|
|
94045
|
+
return next;
|
|
94046
|
+
});
|
|
93583
94047
|
}, []);
|
|
93584
94048
|
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(PromptConfigContext.Provider, {
|
|
93585
94049
|
value: {
|
|
@@ -93600,8 +94064,8 @@ function RootLayout() {
|
|
|
93600
94064
|
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(ThemeProvider, {
|
|
93601
94065
|
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(ToastProvider, {
|
|
93602
94066
|
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(KeyboardLayerProvider, {
|
|
93603
|
-
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(
|
|
93604
|
-
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(
|
|
94067
|
+
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(PromptConfigProvider, {
|
|
94068
|
+
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(DialogProvider, {
|
|
93605
94069
|
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(ThemedRoot, {
|
|
93606
94070
|
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(Outlet, {}, undefined, false, undefined, this)
|
|
93607
94071
|
}, undefined, false, undefined, this)
|
|
@@ -93613,7 +94077,7 @@ function RootLayout() {
|
|
|
93613
94077
|
}
|
|
93614
94078
|
|
|
93615
94079
|
// src/screens/home.tsx
|
|
93616
|
-
var
|
|
94080
|
+
var import_react42 = __toESM(require_react(), 1);
|
|
93617
94081
|
|
|
93618
94082
|
// src/components/header.tsx
|
|
93619
94083
|
function Header() {
|
|
@@ -93641,7 +94105,7 @@ function Header() {
|
|
|
93641
94105
|
}
|
|
93642
94106
|
|
|
93643
94107
|
// src/components/input-bar.tsx
|
|
93644
|
-
var
|
|
94108
|
+
var import_react40 = __toESM(require_react(), 1);
|
|
93645
94109
|
import { readdir } from "fs/promises";
|
|
93646
94110
|
import { isAbsolute as isAbsolute3, relative, resolve as resolve5 } from "path";
|
|
93647
94111
|
|
|
@@ -93659,7 +94123,8 @@ function DialogSearchList({
|
|
|
93659
94123
|
renderItem,
|
|
93660
94124
|
getKey,
|
|
93661
94125
|
placeholder = "Search",
|
|
93662
|
-
emptyText = "No results"
|
|
94126
|
+
emptyText = "No results",
|
|
94127
|
+
onEndReached
|
|
93663
94128
|
}) {
|
|
93664
94129
|
const [selectedIndex, setSelectedIndex] = import_react27.useState(0);
|
|
93665
94130
|
const [searchValue, setSearchValue] = import_react27.useState("");
|
|
@@ -93667,6 +94132,26 @@ function DialogSearchList({
|
|
|
93667
94132
|
const scrollRef = import_react27.useRef(null);
|
|
93668
94133
|
const { isTopLayer } = useKeyboardLayer();
|
|
93669
94134
|
const { colors } = useTheme();
|
|
94135
|
+
const itemsRef = import_react27.useRef(items);
|
|
94136
|
+
itemsRef.current = items;
|
|
94137
|
+
const filterFnRef = import_react27.useRef(filterFn);
|
|
94138
|
+
filterFnRef.current = filterFn;
|
|
94139
|
+
const onSelectRef = import_react27.useRef(onSelect);
|
|
94140
|
+
onSelectRef.current = onSelect;
|
|
94141
|
+
const onHighlightRef = import_react27.useRef(onHighlight);
|
|
94142
|
+
onHighlightRef.current = onHighlight;
|
|
94143
|
+
const selectedIndexRef = import_react27.useRef(selectedIndex);
|
|
94144
|
+
selectedIndexRef.current = selectedIndex;
|
|
94145
|
+
const searchValueRef = import_react27.useRef(searchValue);
|
|
94146
|
+
searchValueRef.current = searchValue;
|
|
94147
|
+
const handleSubmit = import_react27.useCallback(() => {
|
|
94148
|
+
const text2 = inputRef.current?.value ?? "";
|
|
94149
|
+
const currentFiltered = text2 ? itemsRef.current.filter((item2) => filterFnRef.current(item2, text2)) : itemsRef.current;
|
|
94150
|
+
const item = currentFiltered[selectedIndexRef.current];
|
|
94151
|
+
if (item) {
|
|
94152
|
+
onSelectRef.current(item);
|
|
94153
|
+
}
|
|
94154
|
+
}, []);
|
|
93670
94155
|
const handleContentChange = import_react27.useCallback(() => {
|
|
93671
94156
|
const text2 = inputRef.current?.value ?? "";
|
|
93672
94157
|
setSearchValue(text2);
|
|
@@ -93694,8 +94179,8 @@ function DialogSearchList({
|
|
|
93694
94179
|
sb.scrollTo(newIndex);
|
|
93695
94180
|
}
|
|
93696
94181
|
const item = filtered[newIndex];
|
|
93697
|
-
if (item &&
|
|
93698
|
-
|
|
94182
|
+
if (item && onHighlightRef.current)
|
|
94183
|
+
onHighlightRef.current(item);
|
|
93699
94184
|
return newIndex;
|
|
93700
94185
|
});
|
|
93701
94186
|
} else if (key.name === "down") {
|
|
@@ -93710,8 +94195,11 @@ function DialogSearchList({
|
|
|
93710
94195
|
}
|
|
93711
94196
|
}
|
|
93712
94197
|
const item = filtered[newIndex];
|
|
93713
|
-
if (item &&
|
|
93714
|
-
|
|
94198
|
+
if (item && onHighlightRef.current)
|
|
94199
|
+
onHighlightRef.current(item);
|
|
94200
|
+
if (newIndex >= filtered.length - 2 && onEndReached) {
|
|
94201
|
+
onEndReached();
|
|
94202
|
+
}
|
|
93715
94203
|
return newIndex;
|
|
93716
94204
|
});
|
|
93717
94205
|
}
|
|
@@ -93724,7 +94212,8 @@ function DialogSearchList({
|
|
|
93724
94212
|
ref: inputRef,
|
|
93725
94213
|
placeholder,
|
|
93726
94214
|
focused: true,
|
|
93727
|
-
onContentChange: handleContentChange
|
|
94215
|
+
onContentChange: handleContentChange,
|
|
94216
|
+
onSubmit: handleSubmit
|
|
93728
94217
|
}, undefined, false, undefined, this),
|
|
93729
94218
|
filtered.length === 0 ? /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
93730
94219
|
attributes: TextAttributes.DIM,
|
|
@@ -93741,10 +94230,10 @@ function DialogSearchList({
|
|
|
93741
94230
|
backgroundColor: isSelected ? colors.selectMode : undefined,
|
|
93742
94231
|
onMouseMove: () => {
|
|
93743
94232
|
setSelectedIndex(i);
|
|
93744
|
-
if (
|
|
93745
|
-
|
|
94233
|
+
if (onHighlightRef.current)
|
|
94234
|
+
onHighlightRef.current(item);
|
|
93746
94235
|
},
|
|
93747
|
-
onMouseDown: () =>
|
|
94236
|
+
onMouseDown: () => onSelectRef.current(item),
|
|
93748
94237
|
children: renderItem(item, isSelected)
|
|
93749
94238
|
}, getKey(item), false, undefined, this);
|
|
93750
94239
|
})
|
|
@@ -93768,8 +94257,8 @@ var ThemeDialogContent = () => {
|
|
|
93768
94257
|
}, [setTheme]);
|
|
93769
94258
|
const handleSelect = import_react29.useCallback((theme) => {
|
|
93770
94259
|
confirmedRef.current = true;
|
|
93771
|
-
setTheme(theme);
|
|
93772
94260
|
dialog.close();
|
|
94261
|
+
setTheme(theme);
|
|
93773
94262
|
}, [setTheme, dialog]);
|
|
93774
94263
|
const handleHighlight = import_react29.useCallback((theme) => {
|
|
93775
94264
|
setTheme(theme);
|
|
@@ -94119,6 +94608,27 @@ function clearAuth() {
|
|
|
94119
94608
|
}
|
|
94120
94609
|
|
|
94121
94610
|
// src/lib/api-client.ts
|
|
94611
|
+
var RETRY_ATTEMPTS = 3;
|
|
94612
|
+
var RETRY_BASE_DELAY_MS = 1000;
|
|
94613
|
+
async function sleep2(ms) {
|
|
94614
|
+
return new Promise((resolve4) => setTimeout(resolve4, ms));
|
|
94615
|
+
}
|
|
94616
|
+
async function withRetry(fn, options) {
|
|
94617
|
+
const maxAttempts = options?.attempts ?? RETRY_ATTEMPTS;
|
|
94618
|
+
let lastError;
|
|
94619
|
+
for (let attempt = 0;attempt < maxAttempts; attempt++) {
|
|
94620
|
+
try {
|
|
94621
|
+
return await fn(attempt);
|
|
94622
|
+
} catch (err) {
|
|
94623
|
+
lastError = err;
|
|
94624
|
+
if (attempt < maxAttempts - 1) {
|
|
94625
|
+
const delay = RETRY_BASE_DELAY_MS * Math.pow(2, attempt);
|
|
94626
|
+
await sleep2(delay);
|
|
94627
|
+
}
|
|
94628
|
+
}
|
|
94629
|
+
}
|
|
94630
|
+
throw lastError;
|
|
94631
|
+
}
|
|
94122
94632
|
var apiClient = hc(process.env.API_URL ?? "https://lupacodeserver-production.up.railway.app", {
|
|
94123
94633
|
fetch: async (input, init) => {
|
|
94124
94634
|
const headers = new Headers(init?.headers);
|
|
@@ -95577,44 +96087,126 @@ function cleanEscapedString(input) {
|
|
|
95577
96087
|
}
|
|
95578
96088
|
|
|
95579
96089
|
// src/components/dialogs/sessions-dialog.tsx
|
|
96090
|
+
var PAGE_SIZE = 20;
|
|
95580
96091
|
var SessionsDialogContent = () => {
|
|
95581
96092
|
const [sessions, setSessions] = import_react30.useState([]);
|
|
95582
96093
|
const [loading, setLoading] = import_react30.useState(true);
|
|
96094
|
+
const [hasMore, setHasMore] = import_react30.useState(false);
|
|
96095
|
+
const [cursor, setCursor] = import_react30.useState();
|
|
96096
|
+
const [highlightedSession, setHighlightedSession] = import_react30.useState(null);
|
|
96097
|
+
const [view, setView] = import_react30.useState({ type: "list" });
|
|
95583
96098
|
const { close } = useDialog();
|
|
95584
96099
|
const navigate = useNavigate();
|
|
95585
96100
|
const { show } = useToast();
|
|
95586
|
-
|
|
95587
|
-
|
|
95588
|
-
|
|
95589
|
-
|
|
95590
|
-
|
|
95591
|
-
|
|
95592
|
-
|
|
95593
|
-
|
|
95594
|
-
|
|
95595
|
-
|
|
95596
|
-
|
|
95597
|
-
|
|
95598
|
-
|
|
95599
|
-
|
|
95600
|
-
|
|
95601
|
-
|
|
95602
|
-
|
|
95603
|
-
|
|
95604
|
-
|
|
95605
|
-
|
|
95606
|
-
|
|
96101
|
+
const { isTopLayer } = useKeyboardLayer();
|
|
96102
|
+
const { colors } = useTheme();
|
|
96103
|
+
const fetchSessions = import_react30.useCallback(async (cursorVal) => {
|
|
96104
|
+
try {
|
|
96105
|
+
const params = new URLSearchParams;
|
|
96106
|
+
params.set("limit", String(PAGE_SIZE));
|
|
96107
|
+
if (cursorVal)
|
|
96108
|
+
params.set("cursor", cursorVal);
|
|
96109
|
+
const res = await apiClient.sessions.$get({ query: Object.fromEntries(params) });
|
|
96110
|
+
if (!res.ok) {
|
|
96111
|
+
throw new Error(await getErrorMessage2(res));
|
|
96112
|
+
}
|
|
96113
|
+
const raw = await res.json();
|
|
96114
|
+
let list;
|
|
96115
|
+
let more;
|
|
96116
|
+
if (Array.isArray(raw)) {
|
|
96117
|
+
list = raw;
|
|
96118
|
+
more = false;
|
|
96119
|
+
} else {
|
|
96120
|
+
const parsed = raw;
|
|
96121
|
+
list = parsed.sessions ?? [];
|
|
96122
|
+
more = parsed.hasMore ?? false;
|
|
95607
96123
|
}
|
|
95608
|
-
|
|
95609
|
-
|
|
95610
|
-
|
|
95611
|
-
|
|
95612
|
-
|
|
96124
|
+
if (cursorVal) {
|
|
96125
|
+
setSessions((prev) => [...prev, ...list]);
|
|
96126
|
+
} else {
|
|
96127
|
+
setSessions(list);
|
|
96128
|
+
}
|
|
96129
|
+
setHasMore(more);
|
|
96130
|
+
if (list.length > 0) {
|
|
96131
|
+
setCursor(list[list.length - 1].createdAt);
|
|
96132
|
+
}
|
|
96133
|
+
setLoading(false);
|
|
96134
|
+
} catch (error51) {
|
|
96135
|
+
show({
|
|
96136
|
+
variant: "error",
|
|
96137
|
+
message: error51 instanceof Error ? error51.message : "Failed to fetch sessions"
|
|
96138
|
+
});
|
|
96139
|
+
close();
|
|
96140
|
+
}
|
|
95613
96141
|
}, [close, show]);
|
|
96142
|
+
import_react30.useEffect(() => {
|
|
96143
|
+
fetchSessions();
|
|
96144
|
+
}, [fetchSessions]);
|
|
95614
96145
|
const handleSelect = import_react30.useCallback((session) => {
|
|
95615
96146
|
close();
|
|
95616
96147
|
navigate(`/sessions/${session.id}`);
|
|
95617
96148
|
}, [close, navigate]);
|
|
96149
|
+
const handleDelete = import_react30.useCallback(async (session) => {
|
|
96150
|
+
try {
|
|
96151
|
+
const res = await withRetry(() => apiClient.sessions[":id"].$delete({ param: { id: session.id } }));
|
|
96152
|
+
if (!res.ok)
|
|
96153
|
+
throw new Error(await getErrorMessage2(res));
|
|
96154
|
+
show({ variant: "success", message: "Session deleted" });
|
|
96155
|
+
setSessions((prev) => prev.filter((s) => s.id !== session.id));
|
|
96156
|
+
setView({ type: "list" });
|
|
96157
|
+
} catch (error51) {
|
|
96158
|
+
show({
|
|
96159
|
+
variant: "error",
|
|
96160
|
+
message: error51 instanceof Error ? error51.message : "Failed to delete session"
|
|
96161
|
+
});
|
|
96162
|
+
setView({ type: "list" });
|
|
96163
|
+
}
|
|
96164
|
+
}, [show]);
|
|
96165
|
+
const handleRename = import_react30.useCallback(async (session, newTitle) => {
|
|
96166
|
+
try {
|
|
96167
|
+
const res = await withRetry(() => apiClient.sessions[":id"].$patch({
|
|
96168
|
+
param: { id: session.id },
|
|
96169
|
+
json: { title: newTitle }
|
|
96170
|
+
}));
|
|
96171
|
+
if (!res.ok)
|
|
96172
|
+
throw new Error(await getErrorMessage2(res));
|
|
96173
|
+
show({ variant: "success", message: "Session renamed" });
|
|
96174
|
+
setSessions((prev) => prev.map((s) => s.id === session.id ? { ...s, title: newTitle } : s));
|
|
96175
|
+
setView({ type: "list" });
|
|
96176
|
+
} catch (error51) {
|
|
96177
|
+
show({
|
|
96178
|
+
variant: "error",
|
|
96179
|
+
message: error51 instanceof Error ? error51.message : "Failed to rename session"
|
|
96180
|
+
});
|
|
96181
|
+
setView({ type: "list" });
|
|
96182
|
+
}
|
|
96183
|
+
}, [show]);
|
|
96184
|
+
const handleLoadMore = import_react30.useCallback(async () => {
|
|
96185
|
+
if (hasMore && cursor) {
|
|
96186
|
+
await fetchSessions(cursor);
|
|
96187
|
+
}
|
|
96188
|
+
}, [hasMore, cursor, fetchSessions]);
|
|
96189
|
+
useKeyboard((key) => {
|
|
96190
|
+
if (!isTopLayer("dialog"))
|
|
96191
|
+
return;
|
|
96192
|
+
if (view.type === "list") {
|
|
96193
|
+
if (key.name === "d" && highlightedSession) {
|
|
96194
|
+
setView({ type: "confirm-delete", session: highlightedSession });
|
|
96195
|
+
} else if (key.name === "r" && highlightedSession) {
|
|
96196
|
+
setView({ type: "rename", session: highlightedSession });
|
|
96197
|
+
}
|
|
96198
|
+
} else if (view.type === "confirm-delete") {
|
|
96199
|
+
if (key.name === "y" || key.name === "enter") {
|
|
96200
|
+
handleDelete(view.session);
|
|
96201
|
+
} else if (key.name === "n" || key.name === "escape") {
|
|
96202
|
+
setView({ type: "list" });
|
|
96203
|
+
}
|
|
96204
|
+
} else if (view.type === "rename") {
|
|
96205
|
+
if (key.name === "escape") {
|
|
96206
|
+
setView({ type: "list" });
|
|
96207
|
+
}
|
|
96208
|
+
}
|
|
96209
|
+
});
|
|
95618
96210
|
if (loading) {
|
|
95619
96211
|
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
95620
96212
|
flexDirection: "column",
|
|
@@ -95633,35 +96225,94 @@ var SessionsDialogContent = () => {
|
|
|
95633
96225
|
}, undefined, false, undefined, this)
|
|
95634
96226
|
}, undefined, false, undefined, this);
|
|
95635
96227
|
}
|
|
95636
|
-
|
|
95637
|
-
|
|
95638
|
-
|
|
95639
|
-
|
|
95640
|
-
renderItem: (session, isSelected) => /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(import_jsx_dev_runtime2.Fragment, {
|
|
96228
|
+
if (view.type === "confirm-delete") {
|
|
96229
|
+
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
96230
|
+
flexDirection: "column",
|
|
96231
|
+
gap: 1,
|
|
95641
96232
|
children: [
|
|
95642
96233
|
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
95643
|
-
|
|
95644
|
-
|
|
95645
|
-
|
|
95646
|
-
|
|
96234
|
+
children: [
|
|
96235
|
+
'Delete "',
|
|
96236
|
+
view.session.title,
|
|
96237
|
+
'"?'
|
|
96238
|
+
]
|
|
96239
|
+
}, undefined, true, undefined, this),
|
|
95647
96240
|
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
95648
|
-
|
|
95649
|
-
|
|
96241
|
+
flexDirection: "row",
|
|
96242
|
+
gap: 2,
|
|
96243
|
+
children: [
|
|
96244
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
96245
|
+
selectable: true,
|
|
96246
|
+
fg: colors.error,
|
|
96247
|
+
onMouseDown: () => handleDelete(view.session),
|
|
96248
|
+
children: "yes (y)"
|
|
96249
|
+
}, undefined, false, undefined, this),
|
|
96250
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
96251
|
+
selectable: true,
|
|
96252
|
+
onMouseDown: () => setView({ type: "list" }),
|
|
96253
|
+
children: "no (n)"
|
|
96254
|
+
}, undefined, false, undefined, this)
|
|
96255
|
+
]
|
|
96256
|
+
}, undefined, true, undefined, this)
|
|
96257
|
+
]
|
|
96258
|
+
}, undefined, true, undefined, this);
|
|
96259
|
+
}
|
|
96260
|
+
if (view.type === "rename") {
|
|
96261
|
+
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
96262
|
+
flexDirection: "column",
|
|
96263
|
+
gap: 1,
|
|
96264
|
+
children: [
|
|
95650
96265
|
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
95651
|
-
selectable: false,
|
|
95652
|
-
fg: isSelected ? "black" : undefined,
|
|
95653
96266
|
attributes: TextAttributes.DIM,
|
|
95654
|
-
children:
|
|
96267
|
+
children: "Rename session:"
|
|
96268
|
+
}, undefined, false, undefined, this),
|
|
96269
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("input", {
|
|
96270
|
+
focused: true,
|
|
96271
|
+
initialValue: view.session.title,
|
|
96272
|
+
onSubmit: (value) => {
|
|
96273
|
+
if (value.trim()) {
|
|
96274
|
+
handleRename(view.session, value.trim());
|
|
96275
|
+
}
|
|
96276
|
+
}
|
|
95655
96277
|
}, undefined, false, undefined, this)
|
|
95656
96278
|
]
|
|
95657
|
-
}, undefined, true, undefined, this)
|
|
95658
|
-
|
|
95659
|
-
|
|
95660
|
-
|
|
96279
|
+
}, undefined, true, undefined, this);
|
|
96280
|
+
}
|
|
96281
|
+
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
96282
|
+
flexDirection: "column",
|
|
96283
|
+
gap: 1,
|
|
96284
|
+
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(DialogSearchList, {
|
|
96285
|
+
items: sessions,
|
|
96286
|
+
onSelect: handleSelect,
|
|
96287
|
+
onHighlight: (s) => setHighlightedSession(s),
|
|
96288
|
+
filterFn: (s, query) => (s.title || "").toLowerCase().includes(query.toLowerCase()),
|
|
96289
|
+
renderItem: (session, isSelected) => /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(import_jsx_dev_runtime2.Fragment, {
|
|
96290
|
+
children: [
|
|
96291
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
96292
|
+
selectable: false,
|
|
96293
|
+
fg: isSelected ? "black" : "white",
|
|
96294
|
+
children: session.title
|
|
96295
|
+
}, undefined, false, undefined, this),
|
|
96296
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
96297
|
+
flexGrow: 1
|
|
96298
|
+
}, undefined, false, undefined, this),
|
|
96299
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
96300
|
+
selectable: false,
|
|
96301
|
+
fg: isSelected ? "black" : undefined,
|
|
96302
|
+
attributes: TextAttributes.DIM,
|
|
96303
|
+
children: format(new Date(session.createdAt), "hh:mm a")
|
|
96304
|
+
}, undefined, false, undefined, this)
|
|
96305
|
+
]
|
|
96306
|
+
}, undefined, true, undefined, this),
|
|
96307
|
+
getKey: (s) => s.id,
|
|
96308
|
+
placeholder: "Search sessions (r) rename (d) delete",
|
|
96309
|
+
emptyText: "No matching sessions",
|
|
96310
|
+
onEndReached: handleLoadMore
|
|
96311
|
+
}, undefined, false, undefined, this)
|
|
95661
96312
|
}, undefined, false, undefined, this);
|
|
95662
96313
|
};
|
|
95663
96314
|
// src/components/dialogs/agents-dialog.tsx
|
|
95664
|
-
var
|
|
96315
|
+
var import_react32 = __toESM(require_react(), 1);
|
|
95665
96316
|
var AVAILABLE_MODES = [Mode.BUILD, Mode.PLAN];
|
|
95666
96317
|
function getModeLabel(mode) {
|
|
95667
96318
|
return mode === Mode.PLAN ? "Plan" : "Build";
|
|
@@ -95671,9 +96322,9 @@ var AgentsDialogContent = ({
|
|
|
95671
96322
|
onSelectMode
|
|
95672
96323
|
}) => {
|
|
95673
96324
|
const dialog = useDialog();
|
|
95674
|
-
const handleSelect =
|
|
95675
|
-
onSelectMode(nextMode);
|
|
96325
|
+
const handleSelect = import_react32.useCallback((nextMode) => {
|
|
95676
96326
|
dialog.close();
|
|
96327
|
+
onSelectMode(nextMode);
|
|
95677
96328
|
}, [onSelectMode, dialog]);
|
|
95678
96329
|
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(DialogSearchList, {
|
|
95679
96330
|
items: AVAILABLE_MODES,
|
|
@@ -95693,15 +96344,15 @@ var AgentsDialogContent = ({
|
|
|
95693
96344
|
}, undefined, false, undefined, this);
|
|
95694
96345
|
};
|
|
95695
96346
|
// src/components/dialogs/models-dialog.tsx
|
|
95696
|
-
var
|
|
96347
|
+
var import_react33 = __toESM(require_react(), 1);
|
|
95697
96348
|
var ModelsDialogContent = ({
|
|
95698
96349
|
models,
|
|
95699
96350
|
onSelectModel
|
|
95700
96351
|
}) => {
|
|
95701
96352
|
const dialog = useDialog();
|
|
95702
|
-
const handleSelect =
|
|
95703
|
-
onSelectModel(model.id);
|
|
96353
|
+
const handleSelect = import_react33.useCallback((model) => {
|
|
95704
96354
|
dialog.close();
|
|
96355
|
+
onSelectModel(model.id);
|
|
95705
96356
|
}, [dialog, onSelectModel]);
|
|
95706
96357
|
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(DialogSearchList, {
|
|
95707
96358
|
items: models,
|
|
@@ -95737,14 +96388,14 @@ var ModelsDialogContent = ({
|
|
|
95737
96388
|
}, undefined, false, undefined, this);
|
|
95738
96389
|
};
|
|
95739
96390
|
// src/components/dialogs/domains-dialog.tsx
|
|
95740
|
-
var
|
|
96391
|
+
var import_react34 = __toESM(require_react(), 1);
|
|
95741
96392
|
var DomainsDialogContent = ({
|
|
95742
96393
|
onSelectDomain
|
|
95743
96394
|
}) => {
|
|
95744
96395
|
const dialog = useDialog();
|
|
95745
|
-
const handleSelect =
|
|
95746
|
-
onSelectDomain(domain2.id);
|
|
96396
|
+
const handleSelect = import_react34.useCallback((domain2) => {
|
|
95747
96397
|
dialog.close();
|
|
96398
|
+
onSelectDomain(domain2.id);
|
|
95748
96399
|
}, [dialog, onSelectDomain]);
|
|
95749
96400
|
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(DialogSearchList, {
|
|
95750
96401
|
items: [...DOMAINS],
|
|
@@ -95760,6 +96411,274 @@ var DomainsDialogContent = ({
|
|
|
95760
96411
|
emptyText: "No matching domains"
|
|
95761
96412
|
}, undefined, false, undefined, this);
|
|
95762
96413
|
};
|
|
96414
|
+
// src/components/dialogs/settings-dialog.tsx
|
|
96415
|
+
var import_react35 = __toESM(require_react(), 1);
|
|
96416
|
+
// package.json
|
|
96417
|
+
var package_default2 = {
|
|
96418
|
+
name: "lupacode",
|
|
96419
|
+
version: "1.0.1",
|
|
96420
|
+
description: "AI-powered terminal coding assistant",
|
|
96421
|
+
type: "module",
|
|
96422
|
+
bin: {
|
|
96423
|
+
lupacode: "bin/lupacode"
|
|
96424
|
+
},
|
|
96425
|
+
files: [
|
|
96426
|
+
"bin/",
|
|
96427
|
+
"dist/",
|
|
96428
|
+
"README.md"
|
|
96429
|
+
],
|
|
96430
|
+
scripts: {
|
|
96431
|
+
dev: "bun run --watch src/index.tsx",
|
|
96432
|
+
build: 'bun build src/index.tsx --outdir dist --target bun --external "@opentui/core-*"',
|
|
96433
|
+
prepublishOnly: "bun run build",
|
|
96434
|
+
typecheck: "tsc -p tsconfig.json --noEmit"
|
|
96435
|
+
},
|
|
96436
|
+
engines: {
|
|
96437
|
+
bun: ">=1.0.0"
|
|
96438
|
+
},
|
|
96439
|
+
devDependencies: {
|
|
96440
|
+
"@types/bun": "latest",
|
|
96441
|
+
"@types/react": "^19.2.17"
|
|
96442
|
+
},
|
|
96443
|
+
peerDependencies: {
|
|
96444
|
+
typescript: "^5"
|
|
96445
|
+
},
|
|
96446
|
+
peerDependenciesMeta: {
|
|
96447
|
+
typescript: {
|
|
96448
|
+
optional: true
|
|
96449
|
+
}
|
|
96450
|
+
},
|
|
96451
|
+
dependencies: {
|
|
96452
|
+
"@ai-sdk/react": "^4.0.4",
|
|
96453
|
+
"@opentui/core": "^0.3.4",
|
|
96454
|
+
"@opentui/react": "^0.3.4",
|
|
96455
|
+
ai: "^7.0.3",
|
|
96456
|
+
"date-fns": "^4.4.0",
|
|
96457
|
+
dotenv: "^16.4.7",
|
|
96458
|
+
hono: "^4.12.26",
|
|
96459
|
+
open: "^11.0.0",
|
|
96460
|
+
"opentui-spinner": "^0.0.7",
|
|
96461
|
+
"pretty-ms": "^9.3.0",
|
|
96462
|
+
react: "^19.2.6",
|
|
96463
|
+
"react-router": "^8.0.1",
|
|
96464
|
+
zod: "^4.4.3"
|
|
96465
|
+
}
|
|
96466
|
+
};
|
|
96467
|
+
|
|
96468
|
+
// src/lib/update-check.ts
|
|
96469
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync4 } from "fs";
|
|
96470
|
+
import { homedir as homedir3 } from "os";
|
|
96471
|
+
import { join as join4 } from "path";
|
|
96472
|
+
var DIR = join4(homedir3(), ".lupacode");
|
|
96473
|
+
var FILE = join4(DIR, "update-check.json");
|
|
96474
|
+
var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
|
96475
|
+
function readCache() {
|
|
96476
|
+
try {
|
|
96477
|
+
return JSON.parse(readFileSync3(FILE, "utf-8"));
|
|
96478
|
+
} catch {
|
|
96479
|
+
return null;
|
|
96480
|
+
}
|
|
96481
|
+
}
|
|
96482
|
+
function writeCache(data2) {
|
|
96483
|
+
if (!existsSync5(DIR)) {
|
|
96484
|
+
mkdirSync3(DIR, { mode: 448 });
|
|
96485
|
+
}
|
|
96486
|
+
writeFileSync4(FILE, JSON.stringify(data2));
|
|
96487
|
+
}
|
|
96488
|
+
var cachedLatest = null;
|
|
96489
|
+
var cachedCurrent = "0.0.0";
|
|
96490
|
+
function setCurrentVersion(v2) {
|
|
96491
|
+
cachedCurrent = v2;
|
|
96492
|
+
}
|
|
96493
|
+
function getLatestVersion() {
|
|
96494
|
+
return cachedLatest;
|
|
96495
|
+
}
|
|
96496
|
+
async function checkForUpdate(currentVersion) {
|
|
96497
|
+
cachedCurrent = currentVersion;
|
|
96498
|
+
const cache = readCache();
|
|
96499
|
+
if (cache && Date.now() - cache.checkedAt < CHECK_INTERVAL_MS) {
|
|
96500
|
+
cachedLatest = cache.latest;
|
|
96501
|
+
return isNewer(cache.latest, currentVersion) ? cache.latest : null;
|
|
96502
|
+
}
|
|
96503
|
+
try {
|
|
96504
|
+
const res = await fetch("https://registry.npmjs.org/lupacode/latest");
|
|
96505
|
+
if (!res.ok)
|
|
96506
|
+
return null;
|
|
96507
|
+
const data2 = await res.json();
|
|
96508
|
+
const latest = data2.version;
|
|
96509
|
+
const result = { latest, checkedAt: Date.now() };
|
|
96510
|
+
writeCache(result);
|
|
96511
|
+
cachedLatest = latest;
|
|
96512
|
+
return isNewer(latest, currentVersion) ? latest : null;
|
|
96513
|
+
} catch {
|
|
96514
|
+
return null;
|
|
96515
|
+
}
|
|
96516
|
+
}
|
|
96517
|
+
function isNewer(latest, current) {
|
|
96518
|
+
if (!latest)
|
|
96519
|
+
return false;
|
|
96520
|
+
const a = parseSemver(latest);
|
|
96521
|
+
const b2 = parseSemver(current);
|
|
96522
|
+
if (!a || !b2)
|
|
96523
|
+
return false;
|
|
96524
|
+
if (a.major !== b2.major)
|
|
96525
|
+
return a.major > b2.major;
|
|
96526
|
+
if (a.minor !== b2.minor)
|
|
96527
|
+
return a.minor > b2.minor;
|
|
96528
|
+
return a.patch > b2.patch;
|
|
96529
|
+
}
|
|
96530
|
+
function parseSemver(v2) {
|
|
96531
|
+
const m2 = /^v?(\d+)\.(\d+)\.(\d+)/.exec(v2.trim());
|
|
96532
|
+
if (!m2 || m2[1] == null || m2[2] == null || m2[3] == null)
|
|
96533
|
+
return null;
|
|
96534
|
+
return { major: Number(m2[1]), minor: Number(m2[2]), patch: Number(m2[3]) };
|
|
96535
|
+
}
|
|
96536
|
+
function hasUpdate() {
|
|
96537
|
+
return isNewer(cachedLatest, cachedCurrent);
|
|
96538
|
+
}
|
|
96539
|
+
|
|
96540
|
+
// src/components/dialogs/settings-dialog.tsx
|
|
96541
|
+
var ITEMS = ["theme", "mode", "model", "domain"];
|
|
96542
|
+
var SettingsDialogContent = () => {
|
|
96543
|
+
const dialog = useDialog();
|
|
96544
|
+
const { currentTheme, setTheme } = useTheme();
|
|
96545
|
+
const { mode, setMode, model, setModel, domain: domain2, setDomain } = usePromptConfig();
|
|
96546
|
+
const { isTopLayer } = useKeyboardLayer();
|
|
96547
|
+
const [selectedIndex, setSelectedIndex] = import_react35.useState(0);
|
|
96548
|
+
const selectedIndexRef = import_react35.useRef(0);
|
|
96549
|
+
const currentModel = findSupportedChatModel(model);
|
|
96550
|
+
const currentDomain = findDomain(domain2);
|
|
96551
|
+
const openDialogRef = import_react35.useRef(undefined);
|
|
96552
|
+
const openDialog = import_react35.useCallback((item) => {
|
|
96553
|
+
switch (item) {
|
|
96554
|
+
case "theme":
|
|
96555
|
+
dialog.open({ title: "Select Theme", children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(ThemeDialogContent, {}, undefined, false, undefined, this) });
|
|
96556
|
+
break;
|
|
96557
|
+
case "mode":
|
|
96558
|
+
dialog.open({ title: "Select Mode", children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(AgentsDialogContent, {
|
|
96559
|
+
currentMode: mode,
|
|
96560
|
+
onSelectMode: setMode
|
|
96561
|
+
}, undefined, false, undefined, this) });
|
|
96562
|
+
break;
|
|
96563
|
+
case "model":
|
|
96564
|
+
dialog.open({ title: "Select Model", children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(ModelsDialogContent, {
|
|
96565
|
+
models: [...SUPPORTED_CHAT_MODELS],
|
|
96566
|
+
onSelectModel: setModel
|
|
96567
|
+
}, undefined, false, undefined, this) });
|
|
96568
|
+
break;
|
|
96569
|
+
case "domain":
|
|
96570
|
+
dialog.open({ title: "Select Domain", children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(DomainsDialogContent, {
|
|
96571
|
+
onSelectDomain: setDomain
|
|
96572
|
+
}, undefined, false, undefined, this) });
|
|
96573
|
+
break;
|
|
96574
|
+
}
|
|
96575
|
+
}, [dialog, mode, setMode, setModel, setDomain]);
|
|
96576
|
+
openDialogRef.current = openDialog;
|
|
96577
|
+
useKeyboard((key) => {
|
|
96578
|
+
if (!isTopLayer("dialog"))
|
|
96579
|
+
return;
|
|
96580
|
+
if (key.name === "down") {
|
|
96581
|
+
setSelectedIndex((i) => {
|
|
96582
|
+
const next = Math.min(ITEMS.length - 1, i + 1);
|
|
96583
|
+
selectedIndexRef.current = next;
|
|
96584
|
+
return next;
|
|
96585
|
+
});
|
|
96586
|
+
} else if (key.name === "up") {
|
|
96587
|
+
setSelectedIndex((i) => {
|
|
96588
|
+
const next = Math.max(0, i - 1);
|
|
96589
|
+
selectedIndexRef.current = next;
|
|
96590
|
+
return next;
|
|
96591
|
+
});
|
|
96592
|
+
} else if (key.name === "enter" || key.name === "return") {
|
|
96593
|
+
openDialogRef.current?.(ITEMS[selectedIndexRef.current]);
|
|
96594
|
+
}
|
|
96595
|
+
});
|
|
96596
|
+
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
96597
|
+
flexDirection: "column",
|
|
96598
|
+
gap: 1,
|
|
96599
|
+
children: [
|
|
96600
|
+
ITEMS.map((item, i) => {
|
|
96601
|
+
const isSelected = i === selectedIndex;
|
|
96602
|
+
const bgColor = isSelected ? currentTheme.colors.selectMode : undefined;
|
|
96603
|
+
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
96604
|
+
flexDirection: "row",
|
|
96605
|
+
justifyContent: "space-between",
|
|
96606
|
+
alignItems: "center",
|
|
96607
|
+
backgroundColor: bgColor,
|
|
96608
|
+
onMouseDown: () => openDialogRef.current?.(item),
|
|
96609
|
+
children: [
|
|
96610
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
96611
|
+
selectable: false,
|
|
96612
|
+
fg: isSelected ? "black" : undefined,
|
|
96613
|
+
children: item.charAt(0).toUpperCase() + item.slice(1)
|
|
96614
|
+
}, undefined, false, undefined, this),
|
|
96615
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
96616
|
+
flexDirection: "row",
|
|
96617
|
+
gap: 1,
|
|
96618
|
+
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
96619
|
+
selectable: false,
|
|
96620
|
+
fg: isSelected ? "black" : currentTheme.colors.primary,
|
|
96621
|
+
children: [
|
|
96622
|
+
item === "theme" && currentTheme.name,
|
|
96623
|
+
item === "mode" && mode,
|
|
96624
|
+
item === "model" && (currentModel?.id ?? model),
|
|
96625
|
+
item === "domain" && (currentDomain?.name ?? domain2)
|
|
96626
|
+
]
|
|
96627
|
+
}, undefined, true, undefined, this)
|
|
96628
|
+
}, undefined, false, undefined, this)
|
|
96629
|
+
]
|
|
96630
|
+
}, item, true, undefined, this);
|
|
96631
|
+
}),
|
|
96632
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
96633
|
+
paddingTop: 1,
|
|
96634
|
+
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
96635
|
+
attributes: TextAttributes.DIM,
|
|
96636
|
+
children: [
|
|
96637
|
+
"v",
|
|
96638
|
+
package_default2.version,
|
|
96639
|
+
hasUpdate() ? ` \u2192 v${getLatestVersion()} available` : "",
|
|
96640
|
+
" | ",
|
|
96641
|
+
"LupaCode AI Coding Assistant"
|
|
96642
|
+
]
|
|
96643
|
+
}, undefined, true, undefined, this)
|
|
96644
|
+
}, undefined, false, undefined, this)
|
|
96645
|
+
]
|
|
96646
|
+
}, undefined, true, undefined, this);
|
|
96647
|
+
};
|
|
96648
|
+
// src/components/dialogs/keyboard-help-dialog.tsx
|
|
96649
|
+
var shortcuts = [
|
|
96650
|
+
{ key: "tab", description: "Toggle Build/Plan mode" },
|
|
96651
|
+
{ key: "ctrl+d", description: "Switch domain" },
|
|
96652
|
+
{ key: "ctrl+s", description: "Open settings" },
|
|
96653
|
+
{ key: "ctrl+r", description: "Regenerate last assistant response" },
|
|
96654
|
+
{ key: "ctrl+e", description: "Edit last user message" },
|
|
96655
|
+
{ key: "escape", description: "Interrupt response / Cancel / Close dialog" }
|
|
96656
|
+
];
|
|
96657
|
+
var KeyboardHelpDialogContent = () => {
|
|
96658
|
+
const { colors } = useTheme();
|
|
96659
|
+
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
96660
|
+
flexDirection: "column",
|
|
96661
|
+
gap: 1,
|
|
96662
|
+
children: shortcuts.map(({ key, description }) => /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
96663
|
+
flexDirection: "row",
|
|
96664
|
+
gap: 2,
|
|
96665
|
+
children: [
|
|
96666
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
96667
|
+
width: 14,
|
|
96668
|
+
flexShrink: 0,
|
|
96669
|
+
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
96670
|
+
fg: colors.primary,
|
|
96671
|
+
children: key
|
|
96672
|
+
}, undefined, false, undefined, this)
|
|
96673
|
+
}, undefined, false, undefined, this),
|
|
96674
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
96675
|
+
attributes: TextAttributes.DIM,
|
|
96676
|
+
children: description
|
|
96677
|
+
}, undefined, false, undefined, this)
|
|
96678
|
+
]
|
|
96679
|
+
}, key, true, undefined, this))
|
|
96680
|
+
}, undefined, false, undefined, this);
|
|
96681
|
+
};
|
|
95763
96682
|
// src/components/status-bar.tsx
|
|
95764
96683
|
function StatusBar() {
|
|
95765
96684
|
const { colors } = useTheme();
|
|
@@ -95799,6 +96718,9 @@ function StatusBar() {
|
|
|
95799
96718
|
}, undefined, true, undefined, this);
|
|
95800
96719
|
}
|
|
95801
96720
|
|
|
96721
|
+
// src/components/command-menu/commands.tsx
|
|
96722
|
+
var import_react37 = __toESM(require_react(), 1);
|
|
96723
|
+
|
|
95802
96724
|
// ../../node_modules/open/index.js
|
|
95803
96725
|
import process9 from "process";
|
|
95804
96726
|
import path4 from "path";
|
|
@@ -96623,6 +97545,85 @@ var COMMANDS = [
|
|
|
96623
97545
|
}
|
|
96624
97546
|
}
|
|
96625
97547
|
},
|
|
97548
|
+
{
|
|
97549
|
+
name: "rename",
|
|
97550
|
+
description: "Rename the current session",
|
|
97551
|
+
value: "/rename",
|
|
97552
|
+
action: (ctx) => {
|
|
97553
|
+
if (!ctx.sessionId) {
|
|
97554
|
+
ctx.toast.show({ variant: "error", message: "No active session" });
|
|
97555
|
+
return;
|
|
97556
|
+
}
|
|
97557
|
+
const RenameDialog = () => {
|
|
97558
|
+
const [text2, setText] = import_react37.useState("");
|
|
97559
|
+
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
97560
|
+
flexDirection: "column",
|
|
97561
|
+
gap: 1,
|
|
97562
|
+
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("input", {
|
|
97563
|
+
focused: true,
|
|
97564
|
+
placeholder: "New session name",
|
|
97565
|
+
onContentChange: (event) => setText(String(event.value ?? event)),
|
|
97566
|
+
onSubmit: () => {
|
|
97567
|
+
const name23 = text2.trim();
|
|
97568
|
+
if (!name23)
|
|
97569
|
+
return;
|
|
97570
|
+
const baseUrl = process.env.API_URL ?? "https://lupacodeserver-production.up.railway.app";
|
|
97571
|
+
const token = getAuth()?.token ?? "";
|
|
97572
|
+
fetch(`${baseUrl}/sessions/${ctx.sessionId}`, {
|
|
97573
|
+
method: "PATCH",
|
|
97574
|
+
headers: {
|
|
97575
|
+
"Content-Type": "application/json",
|
|
97576
|
+
...token ? { Authorization: `Bearer ${token}` } : {}
|
|
97577
|
+
},
|
|
97578
|
+
body: JSON.stringify({ title: name23 })
|
|
97579
|
+
}).then((res) => {
|
|
97580
|
+
if (!res.ok)
|
|
97581
|
+
throw new Error("Failed to rename");
|
|
97582
|
+
ctx.toast.show({ variant: "success", message: `Renamed to "${name23}"` });
|
|
97583
|
+
}).catch(() => {
|
|
97584
|
+
ctx.toast.show({ variant: "error", message: "Failed to rename session" });
|
|
97585
|
+
});
|
|
97586
|
+
ctx.dialog.close();
|
|
97587
|
+
}
|
|
97588
|
+
}, undefined, false, undefined, this)
|
|
97589
|
+
}, undefined, false, undefined, this);
|
|
97590
|
+
};
|
|
97591
|
+
ctx.dialog.open({ title: "Rename Session", children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(RenameDialog, {}, undefined, false, undefined, this) });
|
|
97592
|
+
}
|
|
97593
|
+
},
|
|
97594
|
+
{
|
|
97595
|
+
name: "export",
|
|
97596
|
+
description: "Export conversation as markdown",
|
|
97597
|
+
value: "/export",
|
|
97598
|
+
action: (ctx) => {
|
|
97599
|
+
if (!ctx.messages || ctx.messages.length === 0) {
|
|
97600
|
+
ctx.toast.show({ variant: "error", message: "No messages to export" });
|
|
97601
|
+
return;
|
|
97602
|
+
}
|
|
97603
|
+
const lines = [];
|
|
97604
|
+
lines.push("# Chat Export");
|
|
97605
|
+
lines.push("");
|
|
97606
|
+
for (const msg of ctx.messages) {
|
|
97607
|
+
const role = msg.role === "user" ? "User" : "Assistant";
|
|
97608
|
+
const text2 = msg.parts.filter((p) => p.type === "text").map((p) => p.text).join("");
|
|
97609
|
+
if (!text2)
|
|
97610
|
+
continue;
|
|
97611
|
+
lines.push(`**${role}:**`);
|
|
97612
|
+
lines.push("");
|
|
97613
|
+
lines.push(text2);
|
|
97614
|
+
lines.push("");
|
|
97615
|
+
}
|
|
97616
|
+
const content = lines.join(`
|
|
97617
|
+
`);
|
|
97618
|
+
const filename = `chat-export-${Date.now()}.md`;
|
|
97619
|
+
try {
|
|
97620
|
+
Bun.write(filename, content);
|
|
97621
|
+
ctx.toast.show({ variant: "success", message: `Exported to ${filename}` });
|
|
97622
|
+
} catch {
|
|
97623
|
+
ctx.toast.show({ variant: "error", message: "Failed to write export file" });
|
|
97624
|
+
}
|
|
97625
|
+
}
|
|
97626
|
+
},
|
|
96626
97627
|
{
|
|
96627
97628
|
name: "exit",
|
|
96628
97629
|
description: "Quit the application",
|
|
@@ -96703,15 +97704,15 @@ function CommandMenu({
|
|
|
96703
97704
|
}
|
|
96704
97705
|
|
|
96705
97706
|
// src/components/command-menu/use-command-menu.ts
|
|
96706
|
-
var
|
|
97707
|
+
var import_react38 = __toESM(require_react(), 1);
|
|
96707
97708
|
function useCommandMenu() {
|
|
96708
|
-
const [textValue, setTextValue] =
|
|
96709
|
-
const [selectedIndex, setSelectedIndex] =
|
|
96710
|
-
const [showCommandMenu, setShowCommandMenu] =
|
|
96711
|
-
const scrollRef =
|
|
97709
|
+
const [textValue, setTextValue] = import_react38.useState("");
|
|
97710
|
+
const [selectedIndex, setSelectedIndex] = import_react38.useState(0);
|
|
97711
|
+
const [showCommandMenu, setShowCommandMenu] = import_react38.useState(false);
|
|
97712
|
+
const scrollRef = import_react38.useRef(null);
|
|
96712
97713
|
const { push, pop, isTopLayer } = useKeyboardLayer();
|
|
96713
97714
|
const commandQuery = showCommandMenu && textValue.startsWith("/") ? textValue.slice(1) : "";
|
|
96714
|
-
const filteredCommands =
|
|
97715
|
+
const filteredCommands = import_react38.useMemo(() => getFilteredCommands(commandQuery), [commandQuery]);
|
|
96715
97716
|
const close = () => {
|
|
96716
97717
|
setShowCommandMenu(false);
|
|
96717
97718
|
pop("command");
|
|
@@ -96724,13 +97725,15 @@ function useCommandMenu() {
|
|
|
96724
97725
|
scrollbox.scrollTo(0);
|
|
96725
97726
|
}
|
|
96726
97727
|
const prefix = text2.startsWith("/") ? text2.slice(1) : null;
|
|
96727
|
-
|
|
97728
|
+
const wasShowing = showCommandMenu;
|
|
97729
|
+
const shouldShow = prefix !== null && !prefix.includes(" ");
|
|
97730
|
+
if (shouldShow && !wasShowing) {
|
|
96728
97731
|
setShowCommandMenu(true);
|
|
96729
97732
|
push("command", () => {
|
|
96730
97733
|
close();
|
|
96731
97734
|
return true;
|
|
96732
97735
|
});
|
|
96733
|
-
} else {
|
|
97736
|
+
} else if (!shouldShow && wasShowing) {
|
|
96734
97737
|
close();
|
|
96735
97738
|
}
|
|
96736
97739
|
};
|
|
@@ -96966,21 +97969,21 @@ var TEXTAREA_KEY_BINDINGS = [
|
|
|
96966
97969
|
{ name: "return", shift: true, action: "newline" },
|
|
96967
97970
|
{ name: "enter", shift: true, action: "newline" }
|
|
96968
97971
|
];
|
|
96969
|
-
function InputBar({ onSubmit, disabled = false }) {
|
|
97972
|
+
function InputBar({ onSubmit, disabled = false, sessionId, messages }) {
|
|
96970
97973
|
const { mode, toggleMode, setMode, setModel, domain: domain2, setDomain } = usePromptConfig();
|
|
96971
|
-
const textareaRef =
|
|
96972
|
-
const onSubmitRef =
|
|
96973
|
-
const activeMentionRef =
|
|
96974
|
-
const mentionScrollRef =
|
|
97974
|
+
const textareaRef = import_react40.useRef(null);
|
|
97975
|
+
const onSubmitRef = import_react40.useRef(() => {});
|
|
97976
|
+
const activeMentionRef = import_react40.useRef(null);
|
|
97977
|
+
const mentionScrollRef = import_react40.useRef(null);
|
|
96975
97978
|
const renderer = useRenderer();
|
|
96976
97979
|
const toast = useToast();
|
|
96977
97980
|
const navigate = useNavigate();
|
|
96978
97981
|
const dialog = useDialog();
|
|
96979
97982
|
const { colors } = useTheme();
|
|
96980
97983
|
const { isTopLayer, setResponder, push, pop } = useKeyboardLayer();
|
|
96981
|
-
const [activeMention, setActiveMention] =
|
|
96982
|
-
const [mentionCandidates, setMentionCandidates] =
|
|
96983
|
-
const [mentionSelectedIndex, setMentionSelectedIndex] =
|
|
97984
|
+
const [activeMention, setActiveMention] = import_react40.useState(null);
|
|
97985
|
+
const [mentionCandidates, setMentionCandidates] = import_react40.useState([]);
|
|
97986
|
+
const [mentionSelectedIndex, setMentionSelectedIndex] = import_react40.useState(0);
|
|
96984
97987
|
const {
|
|
96985
97988
|
showCommandMenu,
|
|
96986
97989
|
commandQuery,
|
|
@@ -96991,13 +97994,13 @@ function InputBar({ onSubmit, disabled = false }) {
|
|
|
96991
97994
|
setSelectedIndex
|
|
96992
97995
|
} = useCommandMenu();
|
|
96993
97996
|
const showMentionMenu = activeMention !== null;
|
|
96994
|
-
const closeMentionMenu =
|
|
97997
|
+
const closeMentionMenu = import_react40.useCallback(() => {
|
|
96995
97998
|
activeMentionRef.current = null;
|
|
96996
97999
|
setActiveMention(null);
|
|
96997
98000
|
setMentionCandidates([]);
|
|
96998
98001
|
pop("mention");
|
|
96999
98002
|
}, [pop]);
|
|
97000
|
-
const syncMentionMenu =
|
|
98003
|
+
const syncMentionMenu = import_react40.useCallback((text2, cursorOffset) => {
|
|
97001
98004
|
const nextMention = findActiveMention(text2, cursorOffset);
|
|
97002
98005
|
const previousMention = activeMentionRef.current;
|
|
97003
98006
|
const mentionChanged = previousMention?.start !== nextMention?.start || previousMention?.end !== nextMention?.end || previousMention?.query !== nextMention?.query;
|
|
@@ -97007,18 +98010,20 @@ function InputBar({ onSubmit, disabled = false }) {
|
|
|
97007
98010
|
}
|
|
97008
98011
|
return;
|
|
97009
98012
|
}
|
|
98013
|
+
if (!previousMention) {
|
|
98014
|
+
push("mention", () => {
|
|
98015
|
+
closeMentionMenu();
|
|
98016
|
+
return true;
|
|
98017
|
+
});
|
|
98018
|
+
}
|
|
97010
98019
|
activeMentionRef.current = nextMention;
|
|
97011
98020
|
setActiveMention(nextMention);
|
|
97012
|
-
push("mention", () => {
|
|
97013
|
-
closeMentionMenu();
|
|
97014
|
-
return true;
|
|
97015
|
-
});
|
|
97016
98021
|
if (mentionChanged) {
|
|
97017
98022
|
setMentionSelectedIndex(0);
|
|
97018
98023
|
mentionScrollRef.current?.scrollTo(0);
|
|
97019
98024
|
}
|
|
97020
98025
|
}, [closeMentionMenu, push]);
|
|
97021
|
-
const handleTextareaContentChange =
|
|
98026
|
+
const handleTextareaContentChange = import_react40.useCallback(() => {
|
|
97022
98027
|
const textarea = textareaRef.current;
|
|
97023
98028
|
if (!textarea)
|
|
97024
98029
|
return;
|
|
@@ -97026,7 +98031,7 @@ function InputBar({ onSubmit, disabled = false }) {
|
|
|
97026
98031
|
handleContentChange(textarea.plainText);
|
|
97027
98032
|
syncMentionMenu(text2, textarea.cursorOffset);
|
|
97028
98033
|
}, [handleContentChange, syncMentionMenu]);
|
|
97029
|
-
const handleSubmit =
|
|
98034
|
+
const handleSubmit = import_react40.useCallback(() => {
|
|
97030
98035
|
if (disabled)
|
|
97031
98036
|
return;
|
|
97032
98037
|
const textarea = textareaRef.current;
|
|
@@ -97038,7 +98043,7 @@ function InputBar({ onSubmit, disabled = false }) {
|
|
|
97038
98043
|
onSubmit(text2);
|
|
97039
98044
|
textarea.setText("");
|
|
97040
98045
|
}, [disabled, onSubmit]);
|
|
97041
|
-
const handleMentionExecute =
|
|
98046
|
+
const handleMentionExecute = import_react40.useCallback((index) => {
|
|
97042
98047
|
const textarea = textareaRef.current;
|
|
97043
98048
|
const mention = activeMentionRef.current;
|
|
97044
98049
|
const candidate = mentionCandidates[index];
|
|
@@ -97050,13 +98055,13 @@ function InputBar({ onSubmit, disabled = false }) {
|
|
|
97050
98055
|
textarea.cursorOffset = mention.start + insertion.length + 1;
|
|
97051
98056
|
syncMentionMenu(nextText, textarea.cursorOffset);
|
|
97052
98057
|
}, [mentionCandidates, syncMentionMenu]);
|
|
97053
|
-
const handleTextareaCursorChange =
|
|
98058
|
+
const handleTextareaCursorChange = import_react40.useCallback(() => {
|
|
97054
98059
|
const textarea = textareaRef.current;
|
|
97055
98060
|
if (!textarea)
|
|
97056
98061
|
return;
|
|
97057
98062
|
syncMentionMenu(textarea.plainText, textarea.cursorOffset);
|
|
97058
98063
|
}, [syncMentionMenu]);
|
|
97059
|
-
const handleCommand =
|
|
98064
|
+
const handleCommand = import_react40.useCallback((command) => {
|
|
97060
98065
|
const textarea = textareaRef.current;
|
|
97061
98066
|
if (!textarea || !command)
|
|
97062
98067
|
return;
|
|
@@ -97070,17 +98075,19 @@ function InputBar({ onSubmit, disabled = false }) {
|
|
|
97070
98075
|
mode,
|
|
97071
98076
|
setMode,
|
|
97072
98077
|
setModel,
|
|
97073
|
-
setDomain
|
|
98078
|
+
setDomain,
|
|
98079
|
+
sessionId,
|
|
98080
|
+
messages
|
|
97074
98081
|
});
|
|
97075
98082
|
} else {
|
|
97076
98083
|
textarea.insertText(command.value + " ");
|
|
97077
98084
|
}
|
|
97078
98085
|
}, [renderer, toast, dialog, navigate, mode, setMode, setModel, setDomain]);
|
|
97079
|
-
const handleCommandExecute =
|
|
98086
|
+
const handleCommandExecute = import_react40.useCallback((index) => {
|
|
97080
98087
|
const command = resolveCommand(index);
|
|
97081
98088
|
handleCommand(command);
|
|
97082
98089
|
}, [resolveCommand, handleCommand]);
|
|
97083
|
-
|
|
98090
|
+
import_react40.useEffect(() => {
|
|
97084
98091
|
if (!activeMention) {
|
|
97085
98092
|
setMentionCandidates([]);
|
|
97086
98093
|
return;
|
|
@@ -97103,7 +98110,7 @@ function InputBar({ onSubmit, disabled = false }) {
|
|
|
97103
98110
|
ignore = true;
|
|
97104
98111
|
};
|
|
97105
98112
|
}, [activeMention]);
|
|
97106
|
-
|
|
98113
|
+
import_react40.useEffect(() => {
|
|
97107
98114
|
const textare = textareaRef.current;
|
|
97108
98115
|
if (!textare)
|
|
97109
98116
|
return;
|
|
@@ -97146,8 +98153,22 @@ function InputBar({ onSubmit, disabled = false }) {
|
|
|
97146
98153
|
}, undefined, false, undefined, this)
|
|
97147
98154
|
});
|
|
97148
98155
|
}
|
|
98156
|
+
if (key.name === "s" && key.ctrl) {
|
|
98157
|
+
key.preventDefault();
|
|
98158
|
+
dialog.open({
|
|
98159
|
+
title: "Settings",
|
|
98160
|
+
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(SettingsDialogContent, {}, undefined, false, undefined, this)
|
|
98161
|
+
});
|
|
98162
|
+
}
|
|
98163
|
+
if (key.name === "?" && !key.ctrl) {
|
|
98164
|
+
key.preventDefault();
|
|
98165
|
+
dialog.open({
|
|
98166
|
+
title: "Keyboard Shortcuts",
|
|
98167
|
+
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(KeyboardHelpDialogContent, {}, undefined, false, undefined, this)
|
|
98168
|
+
});
|
|
98169
|
+
}
|
|
97149
98170
|
});
|
|
97150
|
-
|
|
98171
|
+
import_react40.useEffect(() => {
|
|
97151
98172
|
setResponder("base", () => {
|
|
97152
98173
|
if (disabled)
|
|
97153
98174
|
return false;
|
|
@@ -97260,63 +98281,12 @@ function InputBar({ onSubmit, disabled = false }) {
|
|
|
97260
98281
|
}, undefined, false, undefined, this)
|
|
97261
98282
|
}, undefined, false, undefined, this);
|
|
97262
98283
|
}
|
|
97263
|
-
// package.json
|
|
97264
|
-
var package_default2 = {
|
|
97265
|
-
name: "lupacode",
|
|
97266
|
-
version: "0.2.5",
|
|
97267
|
-
description: "AI-powered terminal coding assistant",
|
|
97268
|
-
type: "module",
|
|
97269
|
-
bin: {
|
|
97270
|
-
lupacode: "bin/lupacode"
|
|
97271
|
-
},
|
|
97272
|
-
files: [
|
|
97273
|
-
"bin/",
|
|
97274
|
-
"dist/",
|
|
97275
|
-
"README.md"
|
|
97276
|
-
],
|
|
97277
|
-
scripts: {
|
|
97278
|
-
dev: "bun run --watch src/index.tsx",
|
|
97279
|
-
build: 'bun build src/index.tsx --outdir dist --target bun --external "@opentui/core-*"',
|
|
97280
|
-
prepublishOnly: "bun run build",
|
|
97281
|
-
typecheck: "tsc -p tsconfig.json --noEmit"
|
|
97282
|
-
},
|
|
97283
|
-
engines: {
|
|
97284
|
-
bun: ">=1.0.0"
|
|
97285
|
-
},
|
|
97286
|
-
devDependencies: {
|
|
97287
|
-
"@types/bun": "latest",
|
|
97288
|
-
"@types/react": "^19.2.17"
|
|
97289
|
-
},
|
|
97290
|
-
peerDependencies: {
|
|
97291
|
-
typescript: "^5"
|
|
97292
|
-
},
|
|
97293
|
-
peerDependenciesMeta: {
|
|
97294
|
-
typescript: {
|
|
97295
|
-
optional: true
|
|
97296
|
-
}
|
|
97297
|
-
},
|
|
97298
|
-
dependencies: {
|
|
97299
|
-
"@ai-sdk/react": "^4.0.4",
|
|
97300
|
-
"@opentui/core": "^0.3.4",
|
|
97301
|
-
"@opentui/react": "^0.3.4",
|
|
97302
|
-
ai: "^7.0.3",
|
|
97303
|
-
"date-fns": "^4.4.0",
|
|
97304
|
-
dotenv: "^16.4.7",
|
|
97305
|
-
hono: "^4.12.26",
|
|
97306
|
-
open: "^11.0.0",
|
|
97307
|
-
"opentui-spinner": "^0.0.7",
|
|
97308
|
-
"pretty-ms": "^9.3.0",
|
|
97309
|
-
react: "^19.2.6",
|
|
97310
|
-
"react-router": "^8.0.1",
|
|
97311
|
-
zod: "^4.4.3"
|
|
97312
|
-
}
|
|
97313
|
-
};
|
|
97314
98284
|
|
|
97315
98285
|
// src/screens/home.tsx
|
|
97316
98286
|
function Home() {
|
|
97317
98287
|
const navigate = useNavigate();
|
|
97318
98288
|
const { mode, model, domain: domain2 } = usePromptConfig();
|
|
97319
|
-
const handleSubmit =
|
|
98289
|
+
const handleSubmit = import_react42.useCallback((text2) => {
|
|
97320
98290
|
navigate("/sessions/new", { state: { message: text2, mode, model, domain: domain2 } });
|
|
97321
98291
|
}, [navigate, mode, model, domain2]);
|
|
97322
98292
|
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
@@ -97347,7 +98317,8 @@ function Home() {
|
|
|
97347
98317
|
attributes: TextAttributes.DIM,
|
|
97348
98318
|
children: [
|
|
97349
98319
|
"v",
|
|
97350
|
-
package_default2.version
|
|
98320
|
+
package_default2.version,
|
|
98321
|
+
hasUpdate() ? ` \u2192 v${getLatestVersion() ?? ""} (npm i -g lupacode)` : ""
|
|
97351
98322
|
]
|
|
97352
98323
|
}, undefined, true, undefined, this),
|
|
97353
98324
|
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
@@ -97371,6 +98342,16 @@ function Home() {
|
|
|
97371
98342
|
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
97372
98343
|
attributes: TextAttributes.DIM,
|
|
97373
98344
|
children: "domains"
|
|
98345
|
+
}, undefined, false, undefined, this),
|
|
98346
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
98347
|
+
children: "\xB7"
|
|
98348
|
+
}, undefined, false, undefined, this),
|
|
98349
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
98350
|
+
children: "ctrl+s"
|
|
98351
|
+
}, undefined, false, undefined, this),
|
|
98352
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
98353
|
+
attributes: TextAttributes.DIM,
|
|
98354
|
+
children: "settings"
|
|
97374
98355
|
}, undefined, false, undefined, this)
|
|
97375
98356
|
]
|
|
97376
98357
|
}, undefined, true, undefined, this)
|
|
@@ -97383,7 +98364,7 @@ function Home() {
|
|
|
97383
98364
|
}
|
|
97384
98365
|
|
|
97385
98366
|
// src/screens/new-session.tsx
|
|
97386
|
-
var
|
|
98367
|
+
var import_react45 = __toESM(require_react(), 1);
|
|
97387
98368
|
|
|
97388
98369
|
// src/components/messages/error-message.tsx
|
|
97389
98370
|
function ErrorMessage({ message: message2 }) {
|
|
@@ -97574,6 +98555,45 @@ function prettyMilliseconds(milliseconds, options) {
|
|
|
97574
98555
|
}
|
|
97575
98556
|
|
|
97576
98557
|
// src/components/messages/bot-message.tsx
|
|
98558
|
+
var globalSyntaxStyle = SyntaxStyle.fromStyles({
|
|
98559
|
+
default: { fg: "#D4D4D4" },
|
|
98560
|
+
keyword: { fg: "#569CD6" },
|
|
98561
|
+
"keyword.control": { fg: "#C586C0" },
|
|
98562
|
+
"keyword.import": { fg: "#C586C0" },
|
|
98563
|
+
"keyword.function": { fg: "#DCDCAA" },
|
|
98564
|
+
string: { fg: "#CE9178" },
|
|
98565
|
+
"string.special": { fg: "#CE9178" },
|
|
98566
|
+
number: { fg: "#B5CEA8" },
|
|
98567
|
+
"number.float": { fg: "#B5CEA8" },
|
|
98568
|
+
comment: { fg: "#6A9955", italic: true },
|
|
98569
|
+
function: { fg: "#DCDCAA" },
|
|
98570
|
+
"function.call": { fg: "#DCDCAA" },
|
|
98571
|
+
"function.method": { fg: "#DCDCAA" },
|
|
98572
|
+
type: { fg: "#4EC9B0" },
|
|
98573
|
+
"type.builtin": { fg: "#4EC9B0" },
|
|
98574
|
+
variable: { fg: "#9CDCFE" },
|
|
98575
|
+
"variable.parameter": { fg: "#9CDCFE" },
|
|
98576
|
+
"variable.builtin": { fg: "#9CDCFE" },
|
|
98577
|
+
constant: { fg: "#4FC1FF" },
|
|
98578
|
+
"constant.builtin": { fg: "#569CD6" },
|
|
98579
|
+
property: { fg: "#9CDCFE" },
|
|
98580
|
+
operator: { fg: "#D4D4D4" },
|
|
98581
|
+
"punctuation.delimiter": { fg: "#D4D4D4" },
|
|
98582
|
+
"punctuation.bracket": { fg: "#D4D4D4" },
|
|
98583
|
+
boolean: { fg: "#569CD6" },
|
|
98584
|
+
label: { fg: "#DCDCAA" },
|
|
98585
|
+
"markup.heading": { fg: "#569CD6", bold: true },
|
|
98586
|
+
"markup.italic": { italic: true },
|
|
98587
|
+
"markup.strong": { fg: "#DCDCAA", bold: true },
|
|
98588
|
+
"markup.strikethrough": { fg: "#888888", italic: true, dim: true },
|
|
98589
|
+
"markup.raw": { fg: "#CE9178" },
|
|
98590
|
+
"markup.link": { fg: "#569CD6", underline: true },
|
|
98591
|
+
"markup.link.label": { fg: "#569CD6", underline: true },
|
|
98592
|
+
"markup.link.url": { fg: "#4FC1FF" },
|
|
98593
|
+
"markup.list": { fg: "#569CD6" },
|
|
98594
|
+
"markup.quote": { fg: "#6A9955", italic: true },
|
|
98595
|
+
conceal: { fg: "#555555" }
|
|
98596
|
+
});
|
|
97577
98597
|
function formatToolName(name23) {
|
|
97578
98598
|
return name23.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/^./, (c) => c.toUpperCase());
|
|
97579
98599
|
}
|
|
@@ -97587,6 +98607,79 @@ function formatToolArgs(tc) {
|
|
|
97587
98607
|
return String(tc.input);
|
|
97588
98608
|
return Object.values(tc.input).map(String).join(" ");
|
|
97589
98609
|
}
|
|
98610
|
+
function isBashTool(tc) {
|
|
98611
|
+
const name23 = tc.type === "dynamic-tool" ? tc.toolName : tc.type.slice("tool-".length);
|
|
98612
|
+
return name23 === "bash";
|
|
98613
|
+
}
|
|
98614
|
+
function isToolRunning(tc) {
|
|
98615
|
+
return tc.state !== "output-available" && tc.state !== "output-error";
|
|
98616
|
+
}
|
|
98617
|
+
function renderToolCall(tc, colors, j2, renderKey) {
|
|
98618
|
+
const toolName = tc.type === "dynamic-tool" ? tc.toolName : tc.type.slice("tool-".length);
|
|
98619
|
+
const running = isToolRunning(tc);
|
|
98620
|
+
const done = tc.state === "output-available";
|
|
98621
|
+
if (isBashTool(tc)) {
|
|
98622
|
+
const command = typeof tc.input === "object" && tc.input != null ? String(tc.input.command ?? "") : "";
|
|
98623
|
+
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
98624
|
+
width: "100%",
|
|
98625
|
+
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
98626
|
+
attributes: TextAttributes.DIM,
|
|
98627
|
+
children: [
|
|
98628
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("em", {
|
|
98629
|
+
fg: colors.success,
|
|
98630
|
+
attributes: TextAttributes.BOLD,
|
|
98631
|
+
children: "$"
|
|
98632
|
+
}, undefined, false, undefined, this),
|
|
98633
|
+
" ",
|
|
98634
|
+
command,
|
|
98635
|
+
running ? "" : "",
|
|
98636
|
+
tc.state === "output-error" ? /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("em", {
|
|
98637
|
+
fg: colors.error,
|
|
98638
|
+
children: [
|
|
98639
|
+
" ",
|
|
98640
|
+
"\u2716",
|
|
98641
|
+
" ",
|
|
98642
|
+
tc.errorText
|
|
98643
|
+
]
|
|
98644
|
+
}, undefined, true, undefined, this) : null
|
|
98645
|
+
]
|
|
98646
|
+
}, undefined, true, undefined, this)
|
|
98647
|
+
}, renderKey, false, undefined, this);
|
|
98648
|
+
}
|
|
98649
|
+
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
98650
|
+
width: "100%",
|
|
98651
|
+
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
98652
|
+
attributes: TextAttributes.DIM,
|
|
98653
|
+
children: [
|
|
98654
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("em", {
|
|
98655
|
+
fg: colors.info,
|
|
98656
|
+
children: [
|
|
98657
|
+
formatToolName(toolName),
|
|
98658
|
+
":"
|
|
98659
|
+
]
|
|
98660
|
+
}, undefined, true, undefined, this),
|
|
98661
|
+
" ",
|
|
98662
|
+
formatToolArgs(tc),
|
|
98663
|
+
running ? "..." : done ? " \u2713" : "",
|
|
98664
|
+
tc.state === "output-error" ? /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("em", {
|
|
98665
|
+
fg: colors.error,
|
|
98666
|
+
children: [
|
|
98667
|
+
" ",
|
|
98668
|
+
"\u2716",
|
|
98669
|
+
" ",
|
|
98670
|
+
tc.errorText
|
|
98671
|
+
]
|
|
98672
|
+
}, undefined, true, undefined, this) : null
|
|
98673
|
+
]
|
|
98674
|
+
}, undefined, true, undefined, this)
|
|
98675
|
+
}, renderKey, false, undefined, this);
|
|
98676
|
+
}
|
|
98677
|
+
function formatTokens(usage) {
|
|
98678
|
+
const total = usage.totalTokens ?? usage.inputTokens ?? usage.outputTokens;
|
|
98679
|
+
if (total == null)
|
|
98680
|
+
return "";
|
|
98681
|
+
return `${total.toLocaleString()} tok`;
|
|
98682
|
+
}
|
|
97590
98683
|
function mergeReasoningParts(parts) {
|
|
97591
98684
|
const reasoningParts = parts.filter((p) => p.type === "reasoning");
|
|
97592
98685
|
if (reasoningParts.length <= 1)
|
|
@@ -97624,6 +98717,7 @@ function BotMessage({
|
|
|
97624
98717
|
model,
|
|
97625
98718
|
mode,
|
|
97626
98719
|
durationMs,
|
|
98720
|
+
usage,
|
|
97627
98721
|
streaming = false
|
|
97628
98722
|
}) {
|
|
97629
98723
|
const { colors } = useTheme();
|
|
@@ -97649,22 +98743,7 @@ function BotMessage({
|
|
|
97649
98743
|
flexDirection: "column",
|
|
97650
98744
|
children: group.parts.map((part, j2) => {
|
|
97651
98745
|
const tc = part;
|
|
97652
|
-
|
|
97653
|
-
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
97654
|
-
attributes: TextAttributes.DIM,
|
|
97655
|
-
children: [
|
|
97656
|
-
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("em", {
|
|
97657
|
-
fg: colors.info,
|
|
97658
|
-
children: [
|
|
97659
|
-
formatToolName(toolName),
|
|
97660
|
-
":"
|
|
97661
|
-
]
|
|
97662
|
-
}, undefined, true, undefined, this),
|
|
97663
|
-
formatToolArgs(tc),
|
|
97664
|
-
tc.state !== "output-available" && tc.state !== "output-error" ? "..." : "",
|
|
97665
|
-
tc.state === "output-error" ? ` ${tc.errorText}` : ""
|
|
97666
|
-
]
|
|
97667
|
-
}, tc.toolCallId, true, undefined, this);
|
|
98746
|
+
return renderToolCall(tc, colors, j2, tc.toolCallId);
|
|
97668
98747
|
})
|
|
97669
98748
|
}, undefined, false, undefined, this)
|
|
97670
98749
|
}, group.key, false, undefined, this);
|
|
@@ -97697,7 +98776,6 @@ function BotMessage({
|
|
|
97697
98776
|
}, `reasoning-${j2}`, false, undefined, this);
|
|
97698
98777
|
}
|
|
97699
98778
|
if (isToolPart(part)) {
|
|
97700
|
-
const toolName = part.type === "dynamic-tool" ? part.toolName : part.type.slice("tool-".length);
|
|
97701
98779
|
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
97702
98780
|
border: ["left"],
|
|
97703
98781
|
borderColor: colors.thinkingBorder,
|
|
@@ -97707,29 +98785,27 @@ function BotMessage({
|
|
|
97707
98785
|
},
|
|
97708
98786
|
width: "100%",
|
|
97709
98787
|
paddingX: 2,
|
|
97710
|
-
children:
|
|
97711
|
-
attributes: TextAttributes.DIM,
|
|
97712
|
-
children: [
|
|
97713
|
-
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("em", {
|
|
97714
|
-
fg: colors.info,
|
|
97715
|
-
children: [
|
|
97716
|
-
formatToolName(toolName),
|
|
97717
|
-
":"
|
|
97718
|
-
]
|
|
97719
|
-
}, undefined, true, undefined, this),
|
|
97720
|
-
formatToolArgs(part),
|
|
97721
|
-
part.state !== "output-available" && part.state !== "output-error" ? "..." : "",
|
|
97722
|
-
part.state === "output-error" ? ` ${part.errorText}` : ""
|
|
97723
|
-
]
|
|
97724
|
-
}, undefined, true, undefined, this)
|
|
98788
|
+
children: renderToolCall(part, colors, j2, part.toolCallId)
|
|
97725
98789
|
}, part.toolCallId, false, undefined, this);
|
|
97726
98790
|
}
|
|
97727
98791
|
if (part.type === "text") {
|
|
97728
98792
|
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
97729
98793
|
paddingX: 3,
|
|
97730
98794
|
width: "100%",
|
|
97731
|
-
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("
|
|
97732
|
-
|
|
98795
|
+
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("markdown", {
|
|
98796
|
+
content: part.text,
|
|
98797
|
+
syntaxStyle: globalSyntaxStyle,
|
|
98798
|
+
conceal: true,
|
|
98799
|
+
concealCode: true,
|
|
98800
|
+
streaming,
|
|
98801
|
+
tableOptions: {
|
|
98802
|
+
style: "grid",
|
|
98803
|
+
borders: true,
|
|
98804
|
+
outerBorder: true,
|
|
98805
|
+
borderStyle: "rounded",
|
|
98806
|
+
cellPadding: 1,
|
|
98807
|
+
borderColor: "#555555"
|
|
98808
|
+
}
|
|
97733
98809
|
}, undefined, false, undefined, this)
|
|
97734
98810
|
}, `text-${j2}`, false, undefined, this);
|
|
97735
98811
|
}
|
|
@@ -97778,6 +98854,19 @@ function BotMessage({
|
|
|
97778
98854
|
children: prettyMilliseconds(durationMs)
|
|
97779
98855
|
}, undefined, false, undefined, this)
|
|
97780
98856
|
]
|
|
98857
|
+
}, undefined, true, undefined, this),
|
|
98858
|
+
usage && formatTokens(usage) && /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(import_jsx_dev_runtime2.Fragment, {
|
|
98859
|
+
children: [
|
|
98860
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
98861
|
+
attributes: TextAttributes.DIM,
|
|
98862
|
+
fg: colors.dimSeparator,
|
|
98863
|
+
children: ">"
|
|
98864
|
+
}, undefined, false, undefined, this),
|
|
98865
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
98866
|
+
attributes: TextAttributes.DIM,
|
|
98867
|
+
children: formatTokens(usage)
|
|
98868
|
+
}, undefined, false, undefined, this)
|
|
98869
|
+
]
|
|
97781
98870
|
}, undefined, true, undefined, this)
|
|
97782
98871
|
]
|
|
97783
98872
|
}, undefined, true, undefined, this)
|
|
@@ -99772,7 +100861,9 @@ function SessionShell({
|
|
|
99772
100861
|
onSubmit,
|
|
99773
100862
|
inputDisabled = false,
|
|
99774
100863
|
loading = false,
|
|
99775
|
-
interruptible = false
|
|
100864
|
+
interruptible = false,
|
|
100865
|
+
sessionId,
|
|
100866
|
+
messages
|
|
99776
100867
|
}) {
|
|
99777
100868
|
const { mode } = usePromptConfig();
|
|
99778
100869
|
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
@@ -99797,7 +100888,9 @@ function SessionShell({
|
|
|
99797
100888
|
flexShrink: 0,
|
|
99798
100889
|
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(InputBar, {
|
|
99799
100890
|
onSubmit,
|
|
99800
|
-
disabled: inputDisabled
|
|
100891
|
+
disabled: inputDisabled,
|
|
100892
|
+
sessionId,
|
|
100893
|
+
messages
|
|
99801
100894
|
}, undefined, false, undefined, this)
|
|
99802
100895
|
}, undefined, false, undefined, this),
|
|
99803
100896
|
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
@@ -99818,7 +100911,8 @@ function SessionShell({
|
|
|
99818
100911
|
attributes: TextAttributes.DIM,
|
|
99819
100912
|
children: [
|
|
99820
100913
|
"v",
|
|
99821
|
-
package_default2.version
|
|
100914
|
+
package_default2.version,
|
|
100915
|
+
hasUpdate() ? ` \u2192 v${getLatestVersion() ?? ""} (npm i -g lupacode)` : ""
|
|
99822
100916
|
]
|
|
99823
100917
|
}, undefined, true, undefined, this),
|
|
99824
100918
|
loading ? /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(import_jsx_dev_runtime2.Fragment, {
|
|
@@ -99855,6 +100949,16 @@ function SessionShell({
|
|
|
99855
100949
|
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
99856
100950
|
attributes: TextAttributes.DIM,
|
|
99857
100951
|
children: "domains"
|
|
100952
|
+
}, undefined, false, undefined, this),
|
|
100953
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
100954
|
+
children: "\xB7"
|
|
100955
|
+
}, undefined, false, undefined, this),
|
|
100956
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
100957
|
+
children: "ctrl+s"
|
|
100958
|
+
}, undefined, false, undefined, this),
|
|
100959
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
100960
|
+
attributes: TextAttributes.DIM,
|
|
100961
|
+
children: "settings"
|
|
99858
100962
|
}, undefined, false, undefined, this)
|
|
99859
100963
|
]
|
|
99860
100964
|
}, undefined, true, undefined, this)
|
|
@@ -99875,17 +100979,17 @@ function NewSession() {
|
|
|
99875
100979
|
const navigate = useNavigate();
|
|
99876
100980
|
const location = useLocation();
|
|
99877
100981
|
const toast = useToast();
|
|
99878
|
-
const hasStartedRef =
|
|
99879
|
-
const state =
|
|
100982
|
+
const hasStartedRef = import_react45.useRef(false);
|
|
100983
|
+
const state = import_react45.useMemo(() => {
|
|
99880
100984
|
const parsed = newSessionStateSchema.safeParse(location.state);
|
|
99881
100985
|
return parsed.success ? parsed.data : null;
|
|
99882
100986
|
}, [location.state]);
|
|
99883
|
-
|
|
100987
|
+
import_react45.useEffect(() => {
|
|
99884
100988
|
if (!state?.message) {
|
|
99885
100989
|
navigate("/", { replace: true });
|
|
99886
100990
|
}
|
|
99887
100991
|
}, [state, navigate]);
|
|
99888
|
-
|
|
100992
|
+
import_react45.useEffect(() => {
|
|
99889
100993
|
if (!state || hasStartedRef.current)
|
|
99890
100994
|
return;
|
|
99891
100995
|
hasStartedRef.current = true;
|
|
@@ -99933,13 +101037,13 @@ function NewSession() {
|
|
|
99933
101037
|
}
|
|
99934
101038
|
|
|
99935
101039
|
// src/screens/sessions.tsx
|
|
99936
|
-
var
|
|
101040
|
+
var import_react54 = __toESM(require_react(), 1);
|
|
99937
101041
|
|
|
99938
101042
|
// src/hooks/use-chat.ts
|
|
99939
|
-
var
|
|
101043
|
+
var import_react52 = __toESM(require_react(), 1);
|
|
99940
101044
|
|
|
99941
101045
|
// ../../node_modules/@ai-sdk/react/dist/index.js
|
|
99942
|
-
var
|
|
101046
|
+
var import_react46 = __toESM(require_react(), 1);
|
|
99943
101047
|
|
|
99944
101048
|
// ../../node_modules/@ai-sdk/react/node_modules/@ai-sdk/provider/dist/index.js
|
|
99945
101049
|
var marker23 = "vercel.ai.error";
|
|
@@ -104692,11 +105796,11 @@ var AbstractChat = class {
|
|
|
104692
105796
|
|
|
104693
105797
|
// ../../node_modules/@ai-sdk/react/dist/index.js
|
|
104694
105798
|
var import_throttleit = __toESM(require_throttleit(), 1);
|
|
104695
|
-
var import_react43 = __toESM(require_react(), 1);
|
|
104696
|
-
var import_react44 = __toESM(require_react(), 1);
|
|
104697
|
-
var import_react45 = __toESM(require_react(), 1);
|
|
104698
|
-
var import_react46 = __toESM(require_react(), 1);
|
|
104699
105799
|
var import_react47 = __toESM(require_react(), 1);
|
|
105800
|
+
var import_react48 = __toESM(require_react(), 1);
|
|
105801
|
+
var import_react49 = __toESM(require_react(), 1);
|
|
105802
|
+
var import_react50 = __toESM(require_react(), 1);
|
|
105803
|
+
var import_react51 = __toESM(require_react(), 1);
|
|
104700
105804
|
var import_jsx_runtime = __toESM(require_jsx_runtime(), 1);
|
|
104701
105805
|
var import_jsx_runtime2 = __toESM(require_jsx_runtime(), 1);
|
|
104702
105806
|
var __accessCheck = (obj, member, msg) => {
|
|
@@ -104833,7 +105937,7 @@ function useChat({
|
|
|
104833
105937
|
resume = false,
|
|
104834
105938
|
...options
|
|
104835
105939
|
} = {}) {
|
|
104836
|
-
const callbacksRef =
|
|
105940
|
+
const callbacksRef = import_react46.useRef(!("chat" in options) ? {
|
|
104837
105941
|
onToolCall: options.onToolCall,
|
|
104838
105942
|
onData: options.onData,
|
|
104839
105943
|
onFinish: options.onFinish,
|
|
@@ -104872,22 +105976,22 @@ function useChat({
|
|
|
104872
105976
|
return (_c = (_b17 = (_a29 = callbacksRef.current).sendAutomaticallyWhen) == null ? undefined : _b17.call(_a29, arg)) != null ? _c : false;
|
|
104873
105977
|
}
|
|
104874
105978
|
};
|
|
104875
|
-
const chatRef =
|
|
105979
|
+
const chatRef = import_react46.useRef("chat" in options ? options.chat : new Chat(optionsWithCallbacks));
|
|
104876
105980
|
const shouldRecreateChat = "chat" in options && options.chat !== chatRef.current || "id" in options && chatRef.current.id !== options.id;
|
|
104877
105981
|
if (shouldRecreateChat) {
|
|
104878
105982
|
chatRef.current = "chat" in options ? options.chat : new Chat(optionsWithCallbacks);
|
|
104879
105983
|
}
|
|
104880
|
-
const subscribeToMessages =
|
|
104881
|
-
const messages =
|
|
104882
|
-
const status =
|
|
104883
|
-
const error51 =
|
|
104884
|
-
const setMessages =
|
|
105984
|
+
const subscribeToMessages = import_react46.useCallback((update) => chatRef.current["~registerMessagesCallback"](update, throttleWaitMs), [throttleWaitMs, chatRef.current.id]);
|
|
105985
|
+
const messages = import_react46.useSyncExternalStore(subscribeToMessages, () => chatRef.current.messages, () => chatRef.current.messages);
|
|
105986
|
+
const status = import_react46.useSyncExternalStore(chatRef.current["~registerStatusCallback"], () => chatRef.current.status, () => chatRef.current.status);
|
|
105987
|
+
const error51 = import_react46.useSyncExternalStore(chatRef.current["~registerErrorCallback"], () => chatRef.current.error, () => chatRef.current.error);
|
|
105988
|
+
const setMessages = import_react46.useCallback((messagesParam) => {
|
|
104885
105989
|
if (typeof messagesParam === "function") {
|
|
104886
105990
|
messagesParam = messagesParam(chatRef.current.messages);
|
|
104887
105991
|
}
|
|
104888
105992
|
chatRef.current.messages = messagesParam;
|
|
104889
105993
|
}, [chatRef]);
|
|
104890
|
-
|
|
105994
|
+
import_react46.useEffect(() => {
|
|
104891
105995
|
if (resume) {
|
|
104892
105996
|
chatRef.current.resumeStream();
|
|
104893
105997
|
}
|
|
@@ -104910,8 +106014,8 @@ function useChat({
|
|
|
104910
106014
|
}
|
|
104911
106015
|
|
|
104912
106016
|
// src/lib/local-tools.ts
|
|
104913
|
-
import { mkdir as mkdir2, readFile as readFile2, readdir as readdir2, stat, writeFile as writeFile2 } from "fs/promises";
|
|
104914
|
-
import { dirname as dirname2, isAbsolute as isAbsolute5, join as
|
|
106017
|
+
import { mkdir as mkdir2, readFile as readFile2, readdir as readdir2, stat, writeFile as writeFile2, unlink as unlink2 } from "fs/promises";
|
|
106018
|
+
import { dirname as dirname2, isAbsolute as isAbsolute5, join as join5, relative as relative2, resolve as resolve7 } from "path";
|
|
104915
106019
|
var MAX_FILE_SIZE = 1e4;
|
|
104916
106020
|
var MAX_RESULTS = 200;
|
|
104917
106021
|
var MAX_MATCHES = 50;
|
|
@@ -104930,7 +106034,7 @@ function truncate(value, limit) {
|
|
|
104930
106034
|
return value.length > limit ? `${value.slice(0, limit)}n... (truncated, ${value.length} total chars)` : value;
|
|
104931
106035
|
}
|
|
104932
106036
|
async function executeLocalTool(toolName, input, mode) {
|
|
104933
|
-
if (mode === Mode.PLAN && !["readFile", "listDirectory", "glob", "grep"].includes(toolName)) {
|
|
106037
|
+
if (mode === Mode.PLAN && !["readFile", "listDirectory", "glob", "grep", "webSearch"].includes(toolName)) {
|
|
104934
106038
|
throw new Error(`Tool ${toolName} is not available in PLAN mode`);
|
|
104935
106039
|
}
|
|
104936
106040
|
switch (toolName) {
|
|
@@ -104948,7 +106052,7 @@ async function executeLocalTool(toolName, input, mode) {
|
|
|
104948
106052
|
for (const entry of entries) {
|
|
104949
106053
|
if (entry.startsWith(".") || entry === "node_modules")
|
|
104950
106054
|
continue;
|
|
104951
|
-
const info = await stat(
|
|
106055
|
+
const info = await stat(join5(resolved, entry));
|
|
104952
106056
|
results.push({ name: entry, type: info.isDirectory() ? "directory" : "file" });
|
|
104953
106057
|
}
|
|
104954
106058
|
results.sort((a2, b2) => a2.type !== b2.type ? a2.type === "directory" ? -1 : 1 : a2.name.localeCompare(b2.name));
|
|
@@ -105040,11 +106144,15 @@ async function executeLocalTool(toolName, input, mode) {
|
|
|
105040
106144
|
}
|
|
105041
106145
|
case "bash": {
|
|
105042
106146
|
const { command, timeout = DEFAULT_TIMEOUT } = toolInputSchemas.bash.parse(input);
|
|
105043
|
-
const
|
|
106147
|
+
const isWindows = process.platform === "win32";
|
|
106148
|
+
const shell = isWindows ? "cmd.exe" : "bash";
|
|
106149
|
+
const shellFlag = isWindows ? "/c" : "-c";
|
|
106150
|
+
const env2 = isWindows ? { ...process.env } : { ...process.env, TERM: "dumb" };
|
|
106151
|
+
const proc = Bun.spawn([shell, shellFlag, command], {
|
|
105044
106152
|
cwd: resolveInsideCwd(".").resolved,
|
|
105045
106153
|
stdout: "pipe",
|
|
105046
106154
|
stderr: "pipe",
|
|
105047
|
-
env:
|
|
106155
|
+
env: env2
|
|
105048
106156
|
});
|
|
105049
106157
|
const timer = setTimeout(() => proc.kill(), timeout);
|
|
105050
106158
|
const [stdout, stderr] = await Promise.all([
|
|
@@ -105059,6 +106167,40 @@ async function executeLocalTool(toolName, input, mode) {
|
|
|
105059
106167
|
exitCode
|
|
105060
106168
|
};
|
|
105061
106169
|
}
|
|
106170
|
+
case "deleteFile": {
|
|
106171
|
+
const { path: path5 } = toolInputSchemas.deleteFile.parse(input);
|
|
106172
|
+
const { cwd, resolved } = resolveInsideCwd(path5);
|
|
106173
|
+
await unlink2(resolved);
|
|
106174
|
+
return { success: true, path: relative2(cwd, resolved) };
|
|
106175
|
+
}
|
|
106176
|
+
case "webSearch": {
|
|
106177
|
+
const { query } = toolInputSchemas.webSearch.parse(input);
|
|
106178
|
+
const apiKey = process.env.TAVILY_API_KEY;
|
|
106179
|
+
if (!apiKey)
|
|
106180
|
+
throw new Error("TAVILY_API_KEY is not set");
|
|
106181
|
+
const res = await fetch("https://api.tavily.com/search", {
|
|
106182
|
+
method: "POST",
|
|
106183
|
+
headers: { "Content-Type": "application/json" },
|
|
106184
|
+
body: JSON.stringify({
|
|
106185
|
+
api_key: apiKey,
|
|
106186
|
+
query,
|
|
106187
|
+
search_depth: "advanced",
|
|
106188
|
+
include_answer: true,
|
|
106189
|
+
max_results: 5
|
|
106190
|
+
})
|
|
106191
|
+
});
|
|
106192
|
+
if (!res.ok)
|
|
106193
|
+
throw new Error(`Web search failed: ${res.status} ${res.statusText}`);
|
|
106194
|
+
const data2 = await res.json();
|
|
106195
|
+
return {
|
|
106196
|
+
results: data2.results.map((r) => ({
|
|
106197
|
+
title: r.title,
|
|
106198
|
+
url: r.url,
|
|
106199
|
+
content: r.content
|
|
106200
|
+
})),
|
|
106201
|
+
answer: data2.answer
|
|
106202
|
+
};
|
|
106203
|
+
}
|
|
105062
106204
|
default:
|
|
105063
106205
|
throw new Error(`Unknown tool ${toolName}`);
|
|
105064
106206
|
}
|
|
@@ -105066,7 +106208,7 @@ async function executeLocalTool(toolName, input, mode) {
|
|
|
105066
106208
|
|
|
105067
106209
|
// src/hooks/use-chat.ts
|
|
105068
106210
|
function useChat2(sessionId, initialMessages) {
|
|
105069
|
-
const transport =
|
|
106211
|
+
const transport = import_react52.useMemo(() => {
|
|
105070
106212
|
return new DefaultChatTransport({
|
|
105071
106213
|
api: apiClient.chat.$url().toString(),
|
|
105072
106214
|
headers() {
|
|
@@ -105124,6 +106266,9 @@ function useChat2(sessionId, initialMessages) {
|
|
|
105124
106266
|
}
|
|
105125
106267
|
});
|
|
105126
106268
|
},
|
|
106269
|
+
append: chat.append,
|
|
106270
|
+
setMessages: chat.setMessages,
|
|
106271
|
+
reload: chat.reload,
|
|
105127
106272
|
abort: chat.stop,
|
|
105128
106273
|
interrupt: chat.stop
|
|
105129
106274
|
};
|
|
@@ -105151,19 +106296,38 @@ function ChatMessage({ msg }) {
|
|
|
105151
106296
|
model: msg.metadata?.model ?? "unknown",
|
|
105152
106297
|
mode: msg.metadata?.mode ?? "BUILD",
|
|
105153
106298
|
durationMs: msg.metadata?.durationMs,
|
|
106299
|
+
usage: msg.metadata?.usage,
|
|
105154
106300
|
streaming: false
|
|
105155
106301
|
}, undefined, false, undefined, this);
|
|
105156
106302
|
}
|
|
106303
|
+
function EditMessageDialog({
|
|
106304
|
+
initialText,
|
|
106305
|
+
onResolve,
|
|
106306
|
+
onSubmit
|
|
106307
|
+
}) {
|
|
106308
|
+
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
106309
|
+
flexDirection: "column",
|
|
106310
|
+
gap: 1,
|
|
106311
|
+
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("input", {
|
|
106312
|
+
focused: true,
|
|
106313
|
+
initialValue: initialText,
|
|
106314
|
+
onContentChange: (v2) => onResolve(v2),
|
|
106315
|
+
onSubmit
|
|
106316
|
+
}, undefined, false, undefined, this)
|
|
106317
|
+
}, undefined, false, undefined, this);
|
|
106318
|
+
}
|
|
105157
106319
|
function SessionChat({
|
|
105158
106320
|
session,
|
|
105159
106321
|
initialPrompt
|
|
105160
106322
|
}) {
|
|
105161
|
-
const [initialMessages] =
|
|
106323
|
+
const [initialMessages] = import_react54.useState(() => session.messages);
|
|
105162
106324
|
const { mode, model, domain: domain2 } = usePromptConfig();
|
|
105163
106325
|
const { isTopLayer } = useKeyboardLayer();
|
|
105164
|
-
const { messages, status, submit, abort, interrupt, error: error51 } = useChat2(session.id, initialMessages);
|
|
105165
|
-
const hasSubmittedInitialPromptRef =
|
|
105166
|
-
|
|
106326
|
+
const { messages, status, submit, setMessages, reload, abort, interrupt, error: error51 } = useChat2(session.id, initialMessages);
|
|
106327
|
+
const hasSubmittedInitialPromptRef = import_react54.useRef(false);
|
|
106328
|
+
const toast = useToast();
|
|
106329
|
+
const dialog = useDialog();
|
|
106330
|
+
import_react54.useEffect(() => {
|
|
105167
106331
|
return () => {
|
|
105168
106332
|
abort();
|
|
105169
106333
|
};
|
|
@@ -105174,7 +106338,55 @@ function SessionChat({
|
|
|
105174
106338
|
interrupt();
|
|
105175
106339
|
}
|
|
105176
106340
|
});
|
|
105177
|
-
|
|
106341
|
+
useKeyboard((key) => {
|
|
106342
|
+
if (key.name === "r" && key.ctrl && isTopLayer("base") && status !== "streaming" && status !== "submitted") {
|
|
106343
|
+
const lastMsg = messages[messages.length - 1];
|
|
106344
|
+
if (lastMsg?.role === "assistant") {
|
|
106345
|
+
key.preventDefault();
|
|
106346
|
+
reload();
|
|
106347
|
+
}
|
|
106348
|
+
}
|
|
106349
|
+
});
|
|
106350
|
+
useKeyboard((key) => {
|
|
106351
|
+
if (key.name === "e" && key.ctrl && isTopLayer("base") && status !== "streaming" && status !== "submitted") {
|
|
106352
|
+
const lastUserMsg = messages.findLast((m2) => m2.role === "user");
|
|
106353
|
+
if (!lastUserMsg)
|
|
106354
|
+
return;
|
|
106355
|
+
key.preventDefault();
|
|
106356
|
+
const currentText = lastUserMsg.parts.filter((p) => p.type === "text").map((p) => p.text).join("");
|
|
106357
|
+
let inputValue = currentText;
|
|
106358
|
+
dialog.open({
|
|
106359
|
+
title: "Edit message",
|
|
106360
|
+
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(EditMessageDialog, {
|
|
106361
|
+
initialText: currentText,
|
|
106362
|
+
onResolve: (text3) => {
|
|
106363
|
+
inputValue = text3;
|
|
106364
|
+
},
|
|
106365
|
+
onSubmit: () => {
|
|
106366
|
+
const idx = messages.findIndex((m2) => m2.id === lastUserMsg.id);
|
|
106367
|
+
if (idx === -1)
|
|
106368
|
+
return;
|
|
106369
|
+
const text3 = inputValue.trim();
|
|
106370
|
+
if (!text3)
|
|
106371
|
+
return;
|
|
106372
|
+
const truncated = messages.slice(0, idx);
|
|
106373
|
+
const editedMsg = {
|
|
106374
|
+
...messages[idx],
|
|
106375
|
+
parts: [{ type: "text", text: text3 }]
|
|
106376
|
+
};
|
|
106377
|
+
setMessages([...truncated, editedMsg]);
|
|
106378
|
+
submit({
|
|
106379
|
+
userText: text3,
|
|
106380
|
+
mode: editedMsg.metadata?.mode ?? mode,
|
|
106381
|
+
model: editedMsg.metadata?.model ?? model
|
|
106382
|
+
});
|
|
106383
|
+
dialog.close();
|
|
106384
|
+
}
|
|
106385
|
+
}, undefined, false, undefined, this)
|
|
106386
|
+
});
|
|
106387
|
+
}
|
|
106388
|
+
});
|
|
106389
|
+
import_react54.useEffect(() => {
|
|
105178
106390
|
if (!initialPrompt || hasSubmittedInitialPromptRef.current)
|
|
105179
106391
|
return;
|
|
105180
106392
|
hasSubmittedInitialPromptRef.current = true;
|
|
@@ -105188,6 +106400,8 @@ function SessionChat({
|
|
|
105188
106400
|
onSubmit: (text3) => submit({ userText: text3, mode, model, domain: domain2 }),
|
|
105189
106401
|
loading: status === "submitted" || status === "streaming",
|
|
105190
106402
|
interruptible: status === "submitted" || status === "streaming",
|
|
106403
|
+
sessionId: session.id,
|
|
106404
|
+
messages,
|
|
105191
106405
|
children: [
|
|
105192
106406
|
messages.map((msg) => /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(ChatMessage, {
|
|
105193
106407
|
msg
|
|
@@ -105203,12 +106417,12 @@ function Session() {
|
|
|
105203
106417
|
const location = useLocation();
|
|
105204
106418
|
const navigate = useNavigate();
|
|
105205
106419
|
const toast = useToast();
|
|
105206
|
-
const prefetched =
|
|
106420
|
+
const prefetched = import_react54.useMemo(() => {
|
|
105207
106421
|
const parsed = sessionLocationSchema.safeParse(location.state);
|
|
105208
106422
|
return parsed.success ? parsed.data : null;
|
|
105209
106423
|
}, [location.state]);
|
|
105210
|
-
const [session, setSession] =
|
|
105211
|
-
|
|
106424
|
+
const [session, setSession] = import_react54.useState(prefetched?.session ?? null);
|
|
106425
|
+
import_react54.useEffect(() => {
|
|
105212
106426
|
if (prefetched?.session)
|
|
105213
106427
|
return;
|
|
105214
106428
|
setSession(null);
|
|
@@ -105275,6 +106489,8 @@ function App() {
|
|
|
105275
106489
|
router
|
|
105276
106490
|
}, undefined, false, undefined, this);
|
|
105277
106491
|
}
|
|
106492
|
+
setCurrentVersion(package_default2.version);
|
|
106493
|
+
checkForUpdate(package_default2.version);
|
|
105278
106494
|
var renderer = await createCliRenderer({
|
|
105279
106495
|
targetFps: 60,
|
|
105280
106496
|
exitOnCtrlC: false
|