@unikode/cli 1.0.17 → 1.0.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +391 -131
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -29,6 +29,40 @@ import { createContext, useContext, useState, useCallback } from "react";
|
|
|
29
29
|
|
|
30
30
|
// src/theme.ts
|
|
31
31
|
var THEMES = [
|
|
32
|
+
{
|
|
33
|
+
name: "Mist",
|
|
34
|
+
colors: {
|
|
35
|
+
primary: "#3B82F6",
|
|
36
|
+
planMode: "#F59E0B",
|
|
37
|
+
selection: "#008ca5ff",
|
|
38
|
+
thinking: "#f59f0be5",
|
|
39
|
+
success: "#22C55E",
|
|
40
|
+
error: "#EF4444",
|
|
41
|
+
info: "#8B5CF6",
|
|
42
|
+
background: "#9db2c4b4",
|
|
43
|
+
surface: "#868c90ff",
|
|
44
|
+
dialogSurface: "#75818a29",
|
|
45
|
+
thinkingBorder: "#D97706",
|
|
46
|
+
dimSeparator: "#94A3B8"
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
name: "Neon Horizon",
|
|
51
|
+
colors: {
|
|
52
|
+
primary: "#00F0FF",
|
|
53
|
+
planMode: "#FF007F",
|
|
54
|
+
selection: "#393153",
|
|
55
|
+
thinking: "#FFB800",
|
|
56
|
+
success: "#00FF66",
|
|
57
|
+
error: "#FF3333",
|
|
58
|
+
info: "#9D4EDD",
|
|
59
|
+
background: "#0D0E15",
|
|
60
|
+
surface: "#1A1C28",
|
|
61
|
+
dialogSurface: "#131520",
|
|
62
|
+
thinkingBorder: "#5A3E85",
|
|
63
|
+
dimSeparator: "#2A2D44"
|
|
64
|
+
}
|
|
65
|
+
},
|
|
32
66
|
{
|
|
33
67
|
name: "Nightfox",
|
|
34
68
|
colors: {
|
|
@@ -746,6 +780,8 @@ function KeyboardLayerProvider({ children }) {
|
|
|
746
780
|
}
|
|
747
781
|
}, []);
|
|
748
782
|
useKeyboard((key) => {
|
|
783
|
+
if (key.name === "f5")
|
|
784
|
+
return;
|
|
749
785
|
if (!key.ctrl || key.name !== "c")
|
|
750
786
|
return;
|
|
751
787
|
const currentStack = stackRef.current;
|
|
@@ -889,14 +925,15 @@ function ThemedRoot({ children }) {
|
|
|
889
925
|
import { createContext as createContext5, useContext as useContext5, useState as useState5, useCallback as useCallback5 } from "react";
|
|
890
926
|
|
|
891
927
|
// ../shared/src/models.ts
|
|
892
|
-
var
|
|
928
|
+
var STATIC_CHAT_MODELS = [
|
|
893
929
|
{
|
|
894
930
|
id: "claude-sonnet-4-6",
|
|
895
931
|
provider: "anthropic",
|
|
896
932
|
pricing: {
|
|
897
933
|
inputUsdPerMillionTokens: 3,
|
|
898
934
|
outputUsdPerMillionTokens: 15
|
|
899
|
-
}
|
|
935
|
+
},
|
|
936
|
+
tools: true
|
|
900
937
|
},
|
|
901
938
|
{
|
|
902
939
|
id: "claude-haiku-4-5",
|
|
@@ -904,7 +941,8 @@ var SUPPORTED_CHAT_MODELS = [
|
|
|
904
941
|
pricing: {
|
|
905
942
|
inputUsdPerMillionTokens: 1,
|
|
906
943
|
outputUsdPerMillionTokens: 5
|
|
907
|
-
}
|
|
944
|
+
},
|
|
945
|
+
tools: true
|
|
908
946
|
},
|
|
909
947
|
{
|
|
910
948
|
id: "claude-opus-4-6",
|
|
@@ -912,7 +950,8 @@ var SUPPORTED_CHAT_MODELS = [
|
|
|
912
950
|
pricing: {
|
|
913
951
|
inputUsdPerMillionTokens: 5,
|
|
914
952
|
outputUsdPerMillionTokens: 25
|
|
915
|
-
}
|
|
953
|
+
},
|
|
954
|
+
tools: true
|
|
916
955
|
},
|
|
917
956
|
{
|
|
918
957
|
id: "gpt-5.4",
|
|
@@ -920,7 +959,8 @@ var SUPPORTED_CHAT_MODELS = [
|
|
|
920
959
|
pricing: {
|
|
921
960
|
inputUsdPerMillionTokens: 2.5,
|
|
922
961
|
outputUsdPerMillionTokens: 15
|
|
923
|
-
}
|
|
962
|
+
},
|
|
963
|
+
tools: true
|
|
924
964
|
},
|
|
925
965
|
{
|
|
926
966
|
id: "gpt-5.4-mini",
|
|
@@ -928,7 +968,8 @@ var SUPPORTED_CHAT_MODELS = [
|
|
|
928
968
|
pricing: {
|
|
929
969
|
inputUsdPerMillionTokens: 0.75,
|
|
930
970
|
outputUsdPerMillionTokens: 4.5
|
|
931
|
-
}
|
|
971
|
+
},
|
|
972
|
+
tools: true
|
|
932
973
|
},
|
|
933
974
|
{
|
|
934
975
|
id: "gpt-5.4-nano",
|
|
@@ -936,7 +977,8 @@ var SUPPORTED_CHAT_MODELS = [
|
|
|
936
977
|
pricing: {
|
|
937
978
|
inputUsdPerMillionTokens: 0.2,
|
|
938
979
|
outputUsdPerMillionTokens: 1.25
|
|
939
|
-
}
|
|
980
|
+
},
|
|
981
|
+
tools: true
|
|
940
982
|
},
|
|
941
983
|
{
|
|
942
984
|
id: "gemini-2.5-flash",
|
|
@@ -944,7 +986,8 @@ var SUPPORTED_CHAT_MODELS = [
|
|
|
944
986
|
pricing: {
|
|
945
987
|
inputUsdPerMillionTokens: 0.3,
|
|
946
988
|
outputUsdPerMillionTokens: 1
|
|
947
|
-
}
|
|
989
|
+
},
|
|
990
|
+
tools: true
|
|
948
991
|
},
|
|
949
992
|
{
|
|
950
993
|
id: "gemini-3.1-flash-lite",
|
|
@@ -952,7 +995,8 @@ var SUPPORTED_CHAT_MODELS = [
|
|
|
952
995
|
pricing: {
|
|
953
996
|
inputUsdPerMillionTokens: 100.25,
|
|
954
997
|
outputUsdPerMillionTokens: 110.5
|
|
955
|
-
}
|
|
998
|
+
},
|
|
999
|
+
tools: true
|
|
956
1000
|
},
|
|
957
1001
|
{
|
|
958
1002
|
id: "ai/smollm2",
|
|
@@ -960,36 +1004,18 @@ var SUPPORTED_CHAT_MODELS = [
|
|
|
960
1004
|
pricing: {
|
|
961
1005
|
inputUsdPerMillionTokens: 2,
|
|
962
1006
|
outputUsdPerMillionTokens: 2
|
|
963
|
-
}
|
|
964
|
-
|
|
965
|
-
{
|
|
966
|
-
id: "gpt-oss:20b-cloud",
|
|
967
|
-
provider: "local-ollama",
|
|
968
|
-
pricing: {
|
|
969
|
-
inputUsdPerMillionTokens: 30,
|
|
970
|
-
outputUsdPerMillionTokens: 30
|
|
971
|
-
}
|
|
972
|
-
},
|
|
973
|
-
{
|
|
974
|
-
id: "qwen3:4b",
|
|
975
|
-
provider: "local-ollama",
|
|
976
|
-
pricing: {
|
|
977
|
-
inputUsdPerMillionTokens: 30,
|
|
978
|
-
outputUsdPerMillionTokens: 30
|
|
979
|
-
}
|
|
980
|
-
},
|
|
981
|
-
{
|
|
982
|
-
id: "gpt-oss:120b-cloud",
|
|
983
|
-
provider: "local-ollama",
|
|
984
|
-
pricing: {
|
|
985
|
-
inputUsdPerMillionTokens: 30,
|
|
986
|
-
outputUsdPerMillionTokens: 30
|
|
987
|
-
}
|
|
1007
|
+
},
|
|
1008
|
+
tools: true
|
|
988
1009
|
}
|
|
989
1010
|
];
|
|
1011
|
+
var SUPPORTED_CHAT_MODELS = [...STATIC_CHAT_MODELS];
|
|
990
1012
|
function findSupportedChatModel(modelId) {
|
|
991
1013
|
return SUPPORTED_CHAT_MODELS.find((model) => model.id === modelId);
|
|
992
1014
|
}
|
|
1015
|
+
function modelSupportsTools(modelId) {
|
|
1016
|
+
const model = findSupportedChatModel(modelId);
|
|
1017
|
+
return model?.tools !== false;
|
|
1018
|
+
}
|
|
993
1019
|
var DEFAULT_CHAT_MODEL_ID = "gemini-2.5-flash";
|
|
994
1020
|
// ../shared/src/schemas.ts
|
|
995
1021
|
import { z } from "zod";
|
|
@@ -997,7 +1023,8 @@ import { tool } from "ai";
|
|
|
997
1023
|
var Mode = {
|
|
998
1024
|
BUILD: "BUILD",
|
|
999
1025
|
PLAN: "PLAN",
|
|
1000
|
-
DOCUMENTATION: "DOCUMENTATION"
|
|
1026
|
+
DOCUMENTATION: "DOCUMENTATION",
|
|
1027
|
+
ASK: "ASK"
|
|
1001
1028
|
};
|
|
1002
1029
|
var allModes = Object.values(Mode);
|
|
1003
1030
|
var modeSchema = z.enum(Object.values(Mode));
|
|
@@ -1158,6 +1185,13 @@ var buildToolContracts = {
|
|
|
1158
1185
|
inputSchema: toolInputSchemas.undoLastEditSchema
|
|
1159
1186
|
})
|
|
1160
1187
|
};
|
|
1188
|
+
var confirmationRequiredTools = new Set([
|
|
1189
|
+
"writeFile",
|
|
1190
|
+
"editFile",
|
|
1191
|
+
"terminalTool",
|
|
1192
|
+
"undoLastEditSchema",
|
|
1193
|
+
"writeMarkdownFile"
|
|
1194
|
+
]);
|
|
1161
1195
|
// src/providers/prompt-config/index.tsx
|
|
1162
1196
|
import { jsxDEV as jsxDEV6 } from "@opentui/react/jsx-dev-runtime";
|
|
1163
1197
|
var PromptConfigContext = createContext5(null);
|
|
@@ -1169,11 +1203,35 @@ function usePromptConfig() {
|
|
|
1169
1203
|
return value;
|
|
1170
1204
|
}
|
|
1171
1205
|
function PromptConfigProvider({ children }) {
|
|
1172
|
-
const
|
|
1173
|
-
const [model,
|
|
1206
|
+
const toast = useToast();
|
|
1207
|
+
const [model, setModelProp] = useState5(DEFAULT_CHAT_MODEL_ID);
|
|
1208
|
+
const [mode, setModeState] = useState5(() => modelSupportsTools(DEFAULT_CHAT_MODEL_ID) ? Mode.BUILD : Mode.ASK);
|
|
1209
|
+
const setMode = useCallback5((newMode) => {
|
|
1210
|
+
setModeState((prevMode) => {
|
|
1211
|
+
const resolvedMode = typeof newMode === "function" ? newMode(prevMode) : newMode;
|
|
1212
|
+
if (!modelSupportsTools(model)) {
|
|
1213
|
+
toast.show({
|
|
1214
|
+
variant: "error",
|
|
1215
|
+
message: 'this model doesnt support tools, and can only be used in the "ASK" mode !!'
|
|
1216
|
+
});
|
|
1217
|
+
return Mode.ASK;
|
|
1218
|
+
}
|
|
1219
|
+
return resolvedMode;
|
|
1220
|
+
});
|
|
1221
|
+
}, [model, toast]);
|
|
1222
|
+
const setModel = useCallback5((newModel) => {
|
|
1223
|
+
setModelProp(newModel);
|
|
1224
|
+
if (!modelSupportsTools(newModel)) {
|
|
1225
|
+
toast.show({
|
|
1226
|
+
variant: "error",
|
|
1227
|
+
message: 'this model doesnt support tools, and can only be used in the "ASK" mode !!'
|
|
1228
|
+
});
|
|
1229
|
+
setModeState(Mode.ASK);
|
|
1230
|
+
}
|
|
1231
|
+
}, [toast]);
|
|
1174
1232
|
const toggleMode = useCallback5(() => {
|
|
1175
1233
|
setMode((m) => m === Mode.BUILD ? Mode.PLAN : Mode.BUILD);
|
|
1176
|
-
}, []);
|
|
1234
|
+
}, [setMode]);
|
|
1177
1235
|
return /* @__PURE__ */ jsxDEV6(PromptConfigContext.Provider, {
|
|
1178
1236
|
value: {
|
|
1179
1237
|
mode,
|
|
@@ -1789,11 +1847,27 @@ var COMMANDS = [
|
|
|
1789
1847
|
name: "models",
|
|
1790
1848
|
description: "select an AI model for generaftion",
|
|
1791
1849
|
value: "/models",
|
|
1792
|
-
action: (ctx) => {
|
|
1850
|
+
action: async (ctx) => {
|
|
1851
|
+
let modelIds;
|
|
1852
|
+
try {
|
|
1853
|
+
const res = await apiClient.models.$get();
|
|
1854
|
+
if (res.ok) {
|
|
1855
|
+
const data = await res.json();
|
|
1856
|
+
if (Array.isArray(data)) {
|
|
1857
|
+
modelIds = data.map((m) => m.id);
|
|
1858
|
+
} else {
|
|
1859
|
+
modelIds = SUPPORTED_CHAT_MODELS.map((m) => m.id);
|
|
1860
|
+
}
|
|
1861
|
+
} else {
|
|
1862
|
+
modelIds = SUPPORTED_CHAT_MODELS.map((m) => m.id);
|
|
1863
|
+
}
|
|
1864
|
+
} catch {
|
|
1865
|
+
modelIds = SUPPORTED_CHAT_MODELS.map((m) => m.id);
|
|
1866
|
+
}
|
|
1793
1867
|
ctx.dialog.open({
|
|
1794
|
-
title: "
|
|
1868
|
+
title: "Model Selection",
|
|
1795
1869
|
children: /* @__PURE__ */ jsxDEV14(ModelsDialogContent, {
|
|
1796
|
-
models:
|
|
1870
|
+
models: modelIds,
|
|
1797
1871
|
onSelectModel: ctx.setModel
|
|
1798
1872
|
}, undefined, false, undefined, this)
|
|
1799
1873
|
});
|
|
@@ -2092,6 +2166,17 @@ function useCommandMenu() {
|
|
|
2092
2166
|
|
|
2093
2167
|
// src/components/input-bar.tsx
|
|
2094
2168
|
import { useNavigate as useNavigate2 } from "react-router";
|
|
2169
|
+
|
|
2170
|
+
// src/lib/textarea-ref.ts
|
|
2171
|
+
var textarea = null;
|
|
2172
|
+
function getInputTextarea() {
|
|
2173
|
+
return textarea;
|
|
2174
|
+
}
|
|
2175
|
+
function setInputTextarea(t) {
|
|
2176
|
+
textarea = t;
|
|
2177
|
+
}
|
|
2178
|
+
|
|
2179
|
+
// src/components/input-bar.tsx
|
|
2095
2180
|
import { jsxDEV as jsxDEV17 } from "@opentui/react/jsx-dev-runtime";
|
|
2096
2181
|
var MAX_VISIBLE_MENTIONS = 8;
|
|
2097
2182
|
var CURRENT_DIRECTORY = process.cwd();
|
|
@@ -2324,48 +2409,48 @@ function InputBar({ onSubmit, disabled = false }) {
|
|
|
2324
2409
|
}
|
|
2325
2410
|
}, [closeMentionMenu, push]);
|
|
2326
2411
|
const handleTextareaContentChange = useCallback11(() => {
|
|
2327
|
-
const
|
|
2328
|
-
if (!
|
|
2412
|
+
const textarea2 = textareaRef.current;
|
|
2413
|
+
if (!textarea2)
|
|
2329
2414
|
return;
|
|
2330
|
-
const text =
|
|
2331
|
-
handleContentChange(
|
|
2332
|
-
syncMentionMenu(text,
|
|
2415
|
+
const text = textarea2.plainText;
|
|
2416
|
+
handleContentChange(textarea2.plainText);
|
|
2417
|
+
syncMentionMenu(text, textarea2.cursorOffset);
|
|
2333
2418
|
}, [handleContentChange, syncMentionMenu]);
|
|
2334
2419
|
const handleSubmit = useCallback11(() => {
|
|
2335
2420
|
if (disabled)
|
|
2336
2421
|
return;
|
|
2337
|
-
const
|
|
2338
|
-
if (!
|
|
2422
|
+
const textarea2 = textareaRef.current;
|
|
2423
|
+
if (!textarea2)
|
|
2339
2424
|
return;
|
|
2340
|
-
const text =
|
|
2425
|
+
const text = textarea2.plainText.trim();
|
|
2341
2426
|
if (text.length === 0)
|
|
2342
2427
|
return;
|
|
2343
2428
|
onSubmit(text);
|
|
2344
|
-
|
|
2429
|
+
textarea2.setText("");
|
|
2345
2430
|
}, [disabled, onSubmit]);
|
|
2346
2431
|
const handleMentionExecute = useCallback11((index) => {
|
|
2347
|
-
const
|
|
2432
|
+
const textarea2 = textareaRef.current;
|
|
2348
2433
|
const mention = activeMentionRef.current;
|
|
2349
2434
|
const candidate = mentionCandidates[index];
|
|
2350
|
-
if (!
|
|
2435
|
+
if (!textarea2 || !mention || !candidate)
|
|
2351
2436
|
return;
|
|
2352
2437
|
const insertion = candidate.kind === "directory" ? candidate.path : `${candidate.path} `;
|
|
2353
|
-
const nextText = `${
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
syncMentionMenu(nextText,
|
|
2438
|
+
const nextText = `${textarea2.plainText.slice(0, mention.start)}@${insertion}${textarea2.plainText.slice(mention.end)}`;
|
|
2439
|
+
textarea2.replaceText(nextText);
|
|
2440
|
+
textarea2.cursorOffset = mention.start + insertion.length + 1;
|
|
2441
|
+
syncMentionMenu(nextText, textarea2.cursorOffset);
|
|
2357
2442
|
}, [mentionCandidates, syncMentionMenu]);
|
|
2358
2443
|
const handleTextareaCursorChange = useCallback11(() => {
|
|
2359
|
-
const
|
|
2360
|
-
if (!
|
|
2444
|
+
const textarea2 = textareaRef.current;
|
|
2445
|
+
if (!textarea2)
|
|
2361
2446
|
return;
|
|
2362
|
-
syncMentionMenu(
|
|
2447
|
+
syncMentionMenu(textarea2.plainText, textarea2.cursorOffset);
|
|
2363
2448
|
}, [syncMentionMenu]);
|
|
2364
2449
|
const handleCommand = useCallback11((command) => {
|
|
2365
|
-
const
|
|
2366
|
-
if (!
|
|
2450
|
+
const textarea2 = textareaRef.current;
|
|
2451
|
+
if (!textarea2 || !command)
|
|
2367
2452
|
return;
|
|
2368
|
-
|
|
2453
|
+
textarea2.setText("");
|
|
2369
2454
|
if (command.action) {
|
|
2370
2455
|
command.action({
|
|
2371
2456
|
exit: () => renderer.destroy(),
|
|
@@ -2377,7 +2462,7 @@ function InputBar({ onSubmit, disabled = false }) {
|
|
|
2377
2462
|
setModel
|
|
2378
2463
|
});
|
|
2379
2464
|
} else {
|
|
2380
|
-
|
|
2465
|
+
textarea2.insertText(command.value + " ");
|
|
2381
2466
|
}
|
|
2382
2467
|
}, [renderer, toast, dialog, navigate, Mode, setMode, setModel]);
|
|
2383
2468
|
const handleCommandExecute = useCallback11((index) => {
|
|
@@ -2408,10 +2493,10 @@ function InputBar({ onSubmit, disabled = false }) {
|
|
|
2408
2493
|
};
|
|
2409
2494
|
}, [activeMention]);
|
|
2410
2495
|
useEffect3(() => {
|
|
2411
|
-
const
|
|
2412
|
-
if (!
|
|
2496
|
+
const textarea2 = textareaRef.current;
|
|
2497
|
+
if (!textarea2)
|
|
2413
2498
|
return;
|
|
2414
|
-
|
|
2499
|
+
textarea2.onSubmit = () => {
|
|
2415
2500
|
onSubmitRef.current();
|
|
2416
2501
|
};
|
|
2417
2502
|
}, []);
|
|
@@ -2444,13 +2529,24 @@ function InputBar({ onSubmit, disabled = false }) {
|
|
|
2444
2529
|
toggleMode();
|
|
2445
2530
|
}
|
|
2446
2531
|
});
|
|
2532
|
+
useKeyboard5((key) => {
|
|
2533
|
+
if (key.name === "f5") {
|
|
2534
|
+
key.preventDefault();
|
|
2535
|
+
const textarea2 = textareaRef.current;
|
|
2536
|
+
if (textarea2 && textarea2.hasSelection()) {
|
|
2537
|
+
const selectedText = textarea2.getSelectedText();
|
|
2538
|
+
renderer.copyToClipboardOSC52(selectedText);
|
|
2539
|
+
toast.show({ variant: "success", message: "Copied to clipboard" });
|
|
2540
|
+
}
|
|
2541
|
+
}
|
|
2542
|
+
});
|
|
2447
2543
|
useEffect3(() => {
|
|
2448
2544
|
setResponder("base", () => {
|
|
2449
2545
|
if (disabled)
|
|
2450
2546
|
return false;
|
|
2451
|
-
const
|
|
2452
|
-
if (
|
|
2453
|
-
|
|
2547
|
+
const textarea2 = textareaRef.current;
|
|
2548
|
+
if (textarea2 && textarea2.plainText.length > 0) {
|
|
2549
|
+
textarea2.setText("");
|
|
2454
2550
|
return true;
|
|
2455
2551
|
}
|
|
2456
2552
|
return false;
|
|
@@ -2494,6 +2590,9 @@ function InputBar({ onSubmit, disabled = false }) {
|
|
|
2494
2590
|
});
|
|
2495
2591
|
}
|
|
2496
2592
|
});
|
|
2593
|
+
useEffect3(() => {
|
|
2594
|
+
setInputTextarea(textareaRef.current);
|
|
2595
|
+
});
|
|
2497
2596
|
return /* @__PURE__ */ jsxDEV17("box", {
|
|
2498
2597
|
width: "100%",
|
|
2499
2598
|
alignItems: "stretch",
|
|
@@ -3061,7 +3160,7 @@ function UserMessage({ message, mode }) {
|
|
|
3061
3160
|
// src/components/messages/bot-message.tsx
|
|
3062
3161
|
import { useMemo as useMemo3 } from "react";
|
|
3063
3162
|
import prettyMs from "pretty-ms";
|
|
3064
|
-
import { SyntaxStyle, TextAttributes as
|
|
3163
|
+
import { SyntaxStyle, TextAttributes as TextAttributes11, getTreeSitterClient, BoxRenderable } from "@opentui/core";
|
|
3065
3164
|
|
|
3066
3165
|
// src/components/messages/question-message.tsx
|
|
3067
3166
|
import { useCallback as useCallback13, useRef as useRef7, useState as useState10 } from "react";
|
|
@@ -3150,8 +3249,71 @@ function QuestionMessage({ prompt, onSubmit }) {
|
|
|
3150
3249
|
}, undefined, false, undefined, this);
|
|
3151
3250
|
}
|
|
3152
3251
|
|
|
3252
|
+
// src/components/messages/confirmation-message.tsx
|
|
3253
|
+
import { TextAttributes as TextAttributes10 } from "@opentui/core";
|
|
3254
|
+
import { jsxDEV as jsxDEV24 } from "@opentui/react/jsx-dev-runtime";
|
|
3255
|
+
function ConfirmationMessage({ confirmation, onAllow, onDisallow }) {
|
|
3256
|
+
const { colors } = useTheme();
|
|
3257
|
+
return /* @__PURE__ */ jsxDEV24("box", {
|
|
3258
|
+
width: "100%",
|
|
3259
|
+
alignItems: "center",
|
|
3260
|
+
children: /* @__PURE__ */ jsxDEV24("box", {
|
|
3261
|
+
border: ["left"],
|
|
3262
|
+
borderColor: colors.error,
|
|
3263
|
+
width: "100%",
|
|
3264
|
+
children: /* @__PURE__ */ jsxDEV24("box", {
|
|
3265
|
+
flexDirection: "column",
|
|
3266
|
+
gap: 1,
|
|
3267
|
+
paddingX: 2,
|
|
3268
|
+
paddingY: 1,
|
|
3269
|
+
backgroundColor: colors.surface,
|
|
3270
|
+
width: "100%",
|
|
3271
|
+
children: [
|
|
3272
|
+
/* @__PURE__ */ jsxDEV24("text", {
|
|
3273
|
+
attributes: TextAttributes10.BOLD,
|
|
3274
|
+
fg: colors.error,
|
|
3275
|
+
children: "Confirmation required"
|
|
3276
|
+
}, undefined, false, undefined, this),
|
|
3277
|
+
/* @__PURE__ */ jsxDEV24("text", {
|
|
3278
|
+
children: confirmation.summary
|
|
3279
|
+
}, undefined, false, undefined, this),
|
|
3280
|
+
/* @__PURE__ */ jsxDEV24("box", {
|
|
3281
|
+
flexDirection: "row",
|
|
3282
|
+
gap: 2,
|
|
3283
|
+
paddingTop: 1,
|
|
3284
|
+
children: [
|
|
3285
|
+
/* @__PURE__ */ jsxDEV24("box", {
|
|
3286
|
+
border: true,
|
|
3287
|
+
paddingX: 2,
|
|
3288
|
+
paddingY: 0,
|
|
3289
|
+
onMouseDown: () => onAllow(confirmation.id),
|
|
3290
|
+
children: /* @__PURE__ */ jsxDEV24("text", {
|
|
3291
|
+
fg: colors.success,
|
|
3292
|
+
attributes: TextAttributes10.BOLD,
|
|
3293
|
+
children: "Allow"
|
|
3294
|
+
}, undefined, false, undefined, this)
|
|
3295
|
+
}, undefined, false, undefined, this),
|
|
3296
|
+
/* @__PURE__ */ jsxDEV24("box", {
|
|
3297
|
+
border: true,
|
|
3298
|
+
paddingX: 2,
|
|
3299
|
+
paddingY: 0,
|
|
3300
|
+
onMouseDown: () => onDisallow(confirmation.id),
|
|
3301
|
+
children: /* @__PURE__ */ jsxDEV24("text", {
|
|
3302
|
+
fg: colors.error,
|
|
3303
|
+
attributes: TextAttributes10.BOLD,
|
|
3304
|
+
children: "Disallow"
|
|
3305
|
+
}, undefined, false, undefined, this)
|
|
3306
|
+
}, undefined, false, undefined, this)
|
|
3307
|
+
]
|
|
3308
|
+
}, undefined, true, undefined, this)
|
|
3309
|
+
]
|
|
3310
|
+
}, undefined, true, undefined, this)
|
|
3311
|
+
}, undefined, false, undefined, this)
|
|
3312
|
+
}, undefined, false, undefined, this);
|
|
3313
|
+
}
|
|
3314
|
+
|
|
3153
3315
|
// src/components/messages/bot-message.tsx
|
|
3154
|
-
import { jsxDEV as
|
|
3316
|
+
import { jsxDEV as jsxDEV25, Fragment as Fragment3 } from "@opentui/react/jsx-dev-runtime";
|
|
3155
3317
|
function formatToolName(name) {
|
|
3156
3318
|
return name.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/^./, (c) => c.toUpperCase());
|
|
3157
3319
|
}
|
|
@@ -3186,7 +3348,10 @@ function BotMessage({
|
|
|
3186
3348
|
durationMs,
|
|
3187
3349
|
streaming = false,
|
|
3188
3350
|
questionPrompts = [],
|
|
3189
|
-
onSubmitQuestionAnswer
|
|
3351
|
+
onSubmitQuestionAnswer,
|
|
3352
|
+
pendingConfirmations = [],
|
|
3353
|
+
onAllowConfirmation,
|
|
3354
|
+
onDisallowConfirmation
|
|
3190
3355
|
}) {
|
|
3191
3356
|
const { colors } = useTheme();
|
|
3192
3357
|
const syntaxStyle = useMemo3(() => SyntaxStyle.fromStyles({
|
|
@@ -3241,24 +3406,24 @@ function BotMessage({
|
|
|
3241
3406
|
return;
|
|
3242
3407
|
};
|
|
3243
3408
|
}, [colors]);
|
|
3244
|
-
return /* @__PURE__ */
|
|
3409
|
+
return /* @__PURE__ */ jsxDEV25("box", {
|
|
3245
3410
|
width: "100%",
|
|
3246
3411
|
alignItems: "center",
|
|
3247
3412
|
children: [
|
|
3248
|
-
groupConsecutiveParts(parts).map((group, i) => /* @__PURE__ */
|
|
3413
|
+
groupConsecutiveParts(parts).map((group, i) => /* @__PURE__ */ jsxDEV25("box", {
|
|
3249
3414
|
width: "100%",
|
|
3250
3415
|
paddingTop: i === 0 ? 0 : 1,
|
|
3251
3416
|
children: group.parts.map((part, j) => {
|
|
3252
3417
|
if (part.type === "reasoning") {
|
|
3253
|
-
return /* @__PURE__ */
|
|
3418
|
+
return /* @__PURE__ */ jsxDEV25("box", {
|
|
3254
3419
|
border: ["left"],
|
|
3255
3420
|
borderColor: colors.thinkingBorder,
|
|
3256
3421
|
width: "100%",
|
|
3257
3422
|
paddingX: 2,
|
|
3258
|
-
children: /* @__PURE__ */
|
|
3259
|
-
attributes:
|
|
3423
|
+
children: /* @__PURE__ */ jsxDEV25("text", {
|
|
3424
|
+
attributes: TextAttributes11.DIM,
|
|
3260
3425
|
children: [
|
|
3261
|
-
/* @__PURE__ */
|
|
3426
|
+
/* @__PURE__ */ jsxDEV25("em", {
|
|
3262
3427
|
fg: colors.thinking,
|
|
3263
3428
|
children: "Thinking:"
|
|
3264
3429
|
}, undefined, false, undefined, this),
|
|
@@ -3272,23 +3437,34 @@ function BotMessage({
|
|
|
3272
3437
|
const toolName = part.type === "dynamic-tool" ? part.toolName : part.type.slice("tool-".length);
|
|
3273
3438
|
const questionPrompt = toolName === "askQuestionTool" ? questionPrompts.find((prompt) => prompt.toolCallId === part.toolCallId) : undefined;
|
|
3274
3439
|
if (questionPrompt) {
|
|
3275
|
-
return /* @__PURE__ */
|
|
3440
|
+
return /* @__PURE__ */ jsxDEV25("box", {
|
|
3276
3441
|
width: "100%",
|
|
3277
|
-
children: /* @__PURE__ */
|
|
3442
|
+
children: /* @__PURE__ */ jsxDEV25(QuestionMessage, {
|
|
3278
3443
|
prompt: questionPrompt,
|
|
3279
3444
|
onSubmit: onSubmitQuestionAnswer ?? (() => {})
|
|
3280
3445
|
}, undefined, false, undefined, this)
|
|
3281
3446
|
}, part.toolCallId, false, undefined, this);
|
|
3282
3447
|
}
|
|
3283
|
-
|
|
3448
|
+
const confirmationPrompt = pendingConfirmations?.find((c) => c.toolCallId === part.toolCallId);
|
|
3449
|
+
if (confirmationPrompt) {
|
|
3450
|
+
return /* @__PURE__ */ jsxDEV25("box", {
|
|
3451
|
+
width: "100%",
|
|
3452
|
+
children: /* @__PURE__ */ jsxDEV25(ConfirmationMessage, {
|
|
3453
|
+
confirmation: confirmationPrompt,
|
|
3454
|
+
onAllow: onAllowConfirmation ?? (() => {}),
|
|
3455
|
+
onDisallow: onDisallowConfirmation ?? (() => {})
|
|
3456
|
+
}, undefined, false, undefined, this)
|
|
3457
|
+
}, `confirm-${part.toolCallId}`, false, undefined, this);
|
|
3458
|
+
}
|
|
3459
|
+
return /* @__PURE__ */ jsxDEV25("box", {
|
|
3284
3460
|
border: ["left"],
|
|
3285
3461
|
borderColor: colors.thinkingBorder,
|
|
3286
3462
|
width: "100%",
|
|
3287
3463
|
paddingX: 2,
|
|
3288
|
-
children: /* @__PURE__ */
|
|
3289
|
-
attributes:
|
|
3464
|
+
children: /* @__PURE__ */ jsxDEV25("text", {
|
|
3465
|
+
attributes: TextAttributes11.DIM,
|
|
3290
3466
|
children: [
|
|
3291
|
-
/* @__PURE__ */
|
|
3467
|
+
/* @__PURE__ */ jsxDEV25("em", {
|
|
3292
3468
|
fg: colors.info,
|
|
3293
3469
|
children: [
|
|
3294
3470
|
formatToolName(toolName),
|
|
@@ -3307,10 +3483,10 @@ function BotMessage({
|
|
|
3307
3483
|
if (j > 0)
|
|
3308
3484
|
return null;
|
|
3309
3485
|
const fullText = group.parts.filter((p) => p.type === "text").map((p) => p.text).join("");
|
|
3310
|
-
return /* @__PURE__ */
|
|
3486
|
+
return /* @__PURE__ */ jsxDEV25("box", {
|
|
3311
3487
|
paddingX: 3,
|
|
3312
3488
|
width: "100%",
|
|
3313
|
-
children: /* @__PURE__ */
|
|
3489
|
+
children: /* @__PURE__ */ jsxDEV25("markdown", {
|
|
3314
3490
|
content: fullText,
|
|
3315
3491
|
syntaxStyle,
|
|
3316
3492
|
streaming,
|
|
@@ -3322,44 +3498,44 @@ function BotMessage({
|
|
|
3322
3498
|
return null;
|
|
3323
3499
|
})
|
|
3324
3500
|
}, group.key, false, undefined, this)),
|
|
3325
|
-
/* @__PURE__ */
|
|
3501
|
+
/* @__PURE__ */ jsxDEV25("box", {
|
|
3326
3502
|
paddingX: 3,
|
|
3327
3503
|
paddingY: 1,
|
|
3328
3504
|
gap: 1,
|
|
3329
3505
|
width: "100%",
|
|
3330
|
-
children: /* @__PURE__ */
|
|
3506
|
+
children: /* @__PURE__ */ jsxDEV25("box", {
|
|
3331
3507
|
flexDirection: "row",
|
|
3332
3508
|
gap: 2,
|
|
3333
3509
|
children: [
|
|
3334
|
-
/* @__PURE__ */
|
|
3510
|
+
/* @__PURE__ */ jsxDEV25("text", {
|
|
3335
3511
|
fg: mode === Mode.PLAN ? colors.planMode : colors.primary,
|
|
3336
3512
|
children: "\u25C9"
|
|
3337
3513
|
}, undefined, false, undefined, this),
|
|
3338
|
-
/* @__PURE__ */
|
|
3514
|
+
/* @__PURE__ */ jsxDEV25("box", {
|
|
3339
3515
|
flexDirection: "row",
|
|
3340
3516
|
gap: 1,
|
|
3341
3517
|
children: [
|
|
3342
|
-
/* @__PURE__ */
|
|
3518
|
+
/* @__PURE__ */ jsxDEV25("text", {
|
|
3343
3519
|
children: mode
|
|
3344
3520
|
}, undefined, false, undefined, this),
|
|
3345
|
-
/* @__PURE__ */
|
|
3346
|
-
attributes:
|
|
3521
|
+
/* @__PURE__ */ jsxDEV25("text", {
|
|
3522
|
+
attributes: TextAttributes11.DIM,
|
|
3347
3523
|
fg: colors.dimSeparator,
|
|
3348
3524
|
children: "\u203A"
|
|
3349
3525
|
}, undefined, false, undefined, this),
|
|
3350
|
-
/* @__PURE__ */
|
|
3351
|
-
attributes:
|
|
3526
|
+
/* @__PURE__ */ jsxDEV25("text", {
|
|
3527
|
+
attributes: TextAttributes11.DIM,
|
|
3352
3528
|
children: model
|
|
3353
3529
|
}, undefined, false, undefined, this),
|
|
3354
|
-
durationMs != null ? /* @__PURE__ */
|
|
3530
|
+
durationMs != null ? /* @__PURE__ */ jsxDEV25(Fragment3, {
|
|
3355
3531
|
children: [
|
|
3356
|
-
/* @__PURE__ */
|
|
3357
|
-
attributes:
|
|
3532
|
+
/* @__PURE__ */ jsxDEV25("text", {
|
|
3533
|
+
attributes: TextAttributes11.DIM,
|
|
3358
3534
|
fg: colors.dimSeparator,
|
|
3359
3535
|
children: "\u203A"
|
|
3360
3536
|
}, undefined, false, undefined, this),
|
|
3361
|
-
/* @__PURE__ */
|
|
3362
|
-
attributes:
|
|
3537
|
+
/* @__PURE__ */ jsxDEV25("text", {
|
|
3538
|
+
attributes: TextAttributes11.DIM,
|
|
3363
3539
|
children: prettyMs(durationMs)
|
|
3364
3540
|
}, undefined, false, undefined, this)
|
|
3365
3541
|
]
|
|
@@ -3373,25 +3549,25 @@ function BotMessage({
|
|
|
3373
3549
|
}, undefined, true, undefined, this);
|
|
3374
3550
|
}
|
|
3375
3551
|
// src/components/messages/error-message.tsx
|
|
3376
|
-
import { TextAttributes as
|
|
3377
|
-
import { jsxDEV as
|
|
3552
|
+
import { TextAttributes as TextAttributes12 } from "@opentui/core";
|
|
3553
|
+
import { jsxDEV as jsxDEV26 } from "@opentui/react/jsx-dev-runtime";
|
|
3378
3554
|
function ErrorMessage({ message }) {
|
|
3379
3555
|
const { colors } = useTheme();
|
|
3380
|
-
return /* @__PURE__ */
|
|
3556
|
+
return /* @__PURE__ */ jsxDEV26("box", {
|
|
3381
3557
|
width: "100%",
|
|
3382
3558
|
alignItems: "center",
|
|
3383
|
-
children: /* @__PURE__ */
|
|
3559
|
+
children: /* @__PURE__ */ jsxDEV26("box", {
|
|
3384
3560
|
border: ["left"],
|
|
3385
3561
|
borderColor: colors.error,
|
|
3386
3562
|
width: "100%",
|
|
3387
|
-
children: /* @__PURE__ */
|
|
3563
|
+
children: /* @__PURE__ */ jsxDEV26("box", {
|
|
3388
3564
|
justifyContent: "center",
|
|
3389
3565
|
paddingX: 2,
|
|
3390
3566
|
paddingY: 1,
|
|
3391
3567
|
backgroundColor: colors.surface,
|
|
3392
3568
|
width: "100%",
|
|
3393
|
-
children: /* @__PURE__ */
|
|
3394
|
-
attributes:
|
|
3569
|
+
children: /* @__PURE__ */ jsxDEV26("text", {
|
|
3570
|
+
attributes: TextAttributes12.DIM,
|
|
3395
3571
|
children: message
|
|
3396
3572
|
}, undefined, false, undefined, this)
|
|
3397
3573
|
}, undefined, false, undefined, this)
|
|
@@ -3399,7 +3575,7 @@ function ErrorMessage({ message }) {
|
|
|
3399
3575
|
}, undefined, false, undefined, this);
|
|
3400
3576
|
}
|
|
3401
3577
|
// src/screens/new-session.tsx
|
|
3402
|
-
import { jsxDEV as
|
|
3578
|
+
import { jsxDEV as jsxDEV27 } from "@opentui/react/jsx-dev-runtime";
|
|
3403
3579
|
var newSessionStateSchema = z2.object({
|
|
3404
3580
|
message: z2.string(),
|
|
3405
3581
|
mode: modeSchema,
|
|
@@ -3455,11 +3631,11 @@ function NewSession() {
|
|
|
3455
3631
|
}, [state, navigate, toast]);
|
|
3456
3632
|
if (!state)
|
|
3457
3633
|
return null;
|
|
3458
|
-
return /* @__PURE__ */
|
|
3634
|
+
return /* @__PURE__ */ jsxDEV27(SessionShell, {
|
|
3459
3635
|
onSubmit: () => {},
|
|
3460
3636
|
inputDisabled: true,
|
|
3461
3637
|
loading: true,
|
|
3462
|
-
children: /* @__PURE__ */
|
|
3638
|
+
children: /* @__PURE__ */ jsxDEV27(UserMessage, {
|
|
3463
3639
|
message: state.message,
|
|
3464
3640
|
mode: state.mode
|
|
3465
3641
|
}, undefined, false, undefined, this)
|
|
@@ -3962,6 +4138,7 @@ ${outline.join(`
|
|
|
3962
4138
|
// src/hooks/use-chat.ts
|
|
3963
4139
|
function useChat(sessionId, initialMessages) {
|
|
3964
4140
|
const [questionPrompts, setQuestionPrompts] = useState11([]);
|
|
4141
|
+
const [pendingConfirmations, setPendingConfirmations] = useState11([]);
|
|
3965
4142
|
const transport = useMemo5(() => {
|
|
3966
4143
|
return new DefaultChatTransport({
|
|
3967
4144
|
api: apiClient.chat.$url().toString(),
|
|
@@ -4004,6 +4181,20 @@ function useChat(sessionId, initialMessages) {
|
|
|
4004
4181
|
}
|
|
4005
4182
|
});
|
|
4006
4183
|
}, [questionPrompts]);
|
|
4184
|
+
const formatToolSummary = (toolName, input) => {
|
|
4185
|
+
switch (toolName) {
|
|
4186
|
+
case "writeFile":
|
|
4187
|
+
return `Create/write file: ${input.path}`;
|
|
4188
|
+
case "editFile":
|
|
4189
|
+
return `Edit file: ${input.path}`;
|
|
4190
|
+
case "terminalTool":
|
|
4191
|
+
return `Run command: ${input.explanation || input.command}`;
|
|
4192
|
+
case "undoLastEditSchema":
|
|
4193
|
+
return `Undo edit: ${input.path}`;
|
|
4194
|
+
default:
|
|
4195
|
+
return `Execute ${toolName}`;
|
|
4196
|
+
}
|
|
4197
|
+
};
|
|
4007
4198
|
const chat = useAiChat({
|
|
4008
4199
|
id: sessionId,
|
|
4009
4200
|
messages: initialMessages,
|
|
@@ -4027,6 +4218,17 @@ function useChat(sessionId, initialMessages) {
|
|
|
4027
4218
|
return;
|
|
4028
4219
|
}
|
|
4029
4220
|
const mode = chat.messages.at(-1)?.metadata?.mode ?? "BUILD";
|
|
4221
|
+
if (confirmationRequiredTools.has(toolCall.toolName)) {
|
|
4222
|
+
const promptId = crypto.randomUUID();
|
|
4223
|
+
setPendingConfirmations((prev) => [...prev, {
|
|
4224
|
+
id: promptId,
|
|
4225
|
+
toolCallId: toolCall.toolCallId,
|
|
4226
|
+
toolName: toolCall.toolName,
|
|
4227
|
+
input: toolCall.input,
|
|
4228
|
+
summary: formatToolSummary(toolCall.toolName, toolCall.input)
|
|
4229
|
+
}]);
|
|
4230
|
+
return;
|
|
4231
|
+
}
|
|
4030
4232
|
executeLocalTool(toolCall.toolName, toolCall.input, mode).then((output) => chat.addToolOutput({
|
|
4031
4233
|
tool: toolCall.toolName,
|
|
4032
4234
|
toolCallId: toolCall.toolCallId,
|
|
@@ -4040,6 +4242,27 @@ function useChat(sessionId, initialMessages) {
|
|
|
4040
4242
|
},
|
|
4041
4243
|
sendAutomaticallyWhen: lastAssistantMessageIsCompleteWithToolCalls
|
|
4042
4244
|
});
|
|
4245
|
+
const allowConfirmation = useCallback14((confirmationId) => {
|
|
4246
|
+
const confirmation = pendingConfirmations.find((c) => c.id === confirmationId);
|
|
4247
|
+
if (!confirmation)
|
|
4248
|
+
return;
|
|
4249
|
+
setPendingConfirmations((prev) => prev.filter((c) => c.id !== confirmationId));
|
|
4250
|
+
const currentMode = chat.messages.at(-1)?.metadata?.mode ?? "BUILD";
|
|
4251
|
+
executeLocalTool(confirmation.toolName, confirmation.input, currentMode).then((output) => chat.addToolOutput({ tool: confirmation.toolName, toolCallId: confirmation.toolCallId, output })).catch((error) => chat.addToolOutput({ tool: confirmation.toolName, toolCallId: confirmation.toolCallId, state: "output-error", errorText: error instanceof Error ? error.message : String(error) }));
|
|
4252
|
+
}, [pendingConfirmations, chat]);
|
|
4253
|
+
const disallowConfirmation = useCallback14((confirmationId) => {
|
|
4254
|
+
const confirmation = pendingConfirmations.find((c) => c.id === confirmationId);
|
|
4255
|
+
if (!confirmation)
|
|
4256
|
+
return;
|
|
4257
|
+
setPendingConfirmations((prev) => prev.filter((c) => c.id !== confirmationId));
|
|
4258
|
+
chat.addToolOutput({
|
|
4259
|
+
tool: confirmation.toolName,
|
|
4260
|
+
toolCallId: confirmation.toolCallId,
|
|
4261
|
+
output: {
|
|
4262
|
+
SYSTEM_CONSTRAINT: "Action Aborted by User. Permission permanently denied for this specific command string. Do NOT retry this command or repeatedly ask user to allow the action. Search for an alternative tool, modify your approach, or explain the limitation to the user."
|
|
4263
|
+
}
|
|
4264
|
+
});
|
|
4265
|
+
}, [pendingConfirmations, chat]);
|
|
4043
4266
|
return {
|
|
4044
4267
|
messages: chat.messages,
|
|
4045
4268
|
status: chat.status,
|
|
@@ -4057,42 +4280,51 @@ function useChat(sessionId, initialMessages) {
|
|
|
4057
4280
|
});
|
|
4058
4281
|
},
|
|
4059
4282
|
abort: chat.stop,
|
|
4060
|
-
interrupt: chat.stop
|
|
4283
|
+
interrupt: chat.stop,
|
|
4284
|
+
pendingConfirmations,
|
|
4285
|
+
allowConfirmation,
|
|
4286
|
+
disallowConfirmation
|
|
4061
4287
|
};
|
|
4062
4288
|
}
|
|
4063
4289
|
|
|
4064
4290
|
// src/screens/session.tsx
|
|
4065
|
-
import { useKeyboard as useKeyboard6 } from "@opentui/react";
|
|
4066
|
-
import { jsxDEV as
|
|
4291
|
+
import { useKeyboard as useKeyboard6, useRenderer as useRenderer3 } from "@opentui/react";
|
|
4292
|
+
import { jsxDEV as jsxDEV28 } from "@opentui/react/jsx-dev-runtime";
|
|
4067
4293
|
var sessionLocationSchema = z3.object({
|
|
4068
4294
|
session: z3.custom((val) => val != null && typeof val === "object" && ("id" in val)),
|
|
4069
4295
|
initialPrompt: z3.object({
|
|
4070
4296
|
message: z3.string(),
|
|
4071
4297
|
mode: z3.custom(),
|
|
4072
|
-
model: z3.
|
|
4298
|
+
model: z3.string()
|
|
4073
4299
|
}).optional()
|
|
4074
4300
|
});
|
|
4075
4301
|
function ChatMessage({
|
|
4076
4302
|
msg,
|
|
4077
4303
|
questionPrompts,
|
|
4078
4304
|
onSubmitQuestionAnswer,
|
|
4305
|
+
pendingConfirmations,
|
|
4306
|
+
onAllowConfirmation,
|
|
4307
|
+
onDisallowConfirmation,
|
|
4079
4308
|
isStreaming = false
|
|
4080
4309
|
}) {
|
|
4081
4310
|
if (msg.role === "user") {
|
|
4082
4311
|
const text = msg.parts.filter((p) => p.type === "text").map((p) => p.text).join("");
|
|
4083
|
-
return /* @__PURE__ */
|
|
4312
|
+
return /* @__PURE__ */ jsxDEV28(UserMessage, {
|
|
4084
4313
|
message: text,
|
|
4085
4314
|
mode: msg.metadata?.mode ?? "BUILD"
|
|
4086
4315
|
}, undefined, false, undefined, this);
|
|
4087
4316
|
}
|
|
4088
|
-
return /* @__PURE__ */
|
|
4317
|
+
return /* @__PURE__ */ jsxDEV28(BotMessage, {
|
|
4089
4318
|
parts: msg.parts,
|
|
4090
4319
|
model: msg.metadata?.model ?? "unknown",
|
|
4091
4320
|
mode: msg.metadata?.mode ?? "BUILD",
|
|
4092
4321
|
durationMs: msg.metadata?.durationMs,
|
|
4093
4322
|
streaming: isStreaming,
|
|
4094
4323
|
questionPrompts,
|
|
4095
|
-
onSubmitQuestionAnswer
|
|
4324
|
+
onSubmitQuestionAnswer,
|
|
4325
|
+
pendingConfirmations,
|
|
4326
|
+
onAllowConfirmation,
|
|
4327
|
+
onDisallowConfirmation
|
|
4096
4328
|
}, undefined, false, undefined, this);
|
|
4097
4329
|
}
|
|
4098
4330
|
function SessionChat({ session, initialPrompt }) {
|
|
@@ -4106,11 +4338,16 @@ function SessionChat({ session, initialPrompt }) {
|
|
|
4106
4338
|
error,
|
|
4107
4339
|
questionPrompts,
|
|
4108
4340
|
submitQuestionAnswer,
|
|
4109
|
-
deactivateQuestionPrompts
|
|
4341
|
+
deactivateQuestionPrompts,
|
|
4342
|
+
pendingConfirmations,
|
|
4343
|
+
allowConfirmation,
|
|
4344
|
+
disallowConfirmation
|
|
4110
4345
|
} = useChat(session.id, initialMessages);
|
|
4111
4346
|
const hasSubmittedInitialPromptRef = useRef9(false);
|
|
4112
4347
|
const { mode, model } = usePromptConfig();
|
|
4113
4348
|
const { isTopLayer } = useKeyboardLayer();
|
|
4349
|
+
const renderer = useRenderer3();
|
|
4350
|
+
const toast = useToast();
|
|
4114
4351
|
useEffect5(() => {
|
|
4115
4352
|
return () => {
|
|
4116
4353
|
abort();
|
|
@@ -4122,6 +4359,25 @@ function SessionChat({ session, initialPrompt }) {
|
|
|
4122
4359
|
interrupt();
|
|
4123
4360
|
}
|
|
4124
4361
|
});
|
|
4362
|
+
useKeyboard6((key) => {
|
|
4363
|
+
if (key.name === "f5") {
|
|
4364
|
+
key.preventDefault();
|
|
4365
|
+
const inputTextarea = getInputTextarea();
|
|
4366
|
+
if (inputTextarea && inputTextarea.hasSelection()) {
|
|
4367
|
+
renderer.copyToClipboardOSC52(inputTextarea.getSelectedText());
|
|
4368
|
+
toast.show({ variant: "success", message: "Copied to clipboard" });
|
|
4369
|
+
return;
|
|
4370
|
+
}
|
|
4371
|
+
const lastAssistantMessage = messages.findLast((m) => m.role === "assistant");
|
|
4372
|
+
if (lastAssistantMessage) {
|
|
4373
|
+
const text = lastAssistantMessage.parts.filter((p) => p.type === "text").map((p) => p.text).join("");
|
|
4374
|
+
if (text) {
|
|
4375
|
+
renderer.copyToClipboardOSC52(text);
|
|
4376
|
+
toast.show({ variant: "success", message: "Copied last response to clipboard" });
|
|
4377
|
+
}
|
|
4378
|
+
}
|
|
4379
|
+
}
|
|
4380
|
+
});
|
|
4125
4381
|
useEffect5(() => {
|
|
4126
4382
|
if (!initialPrompt || hasSubmittedInitialPromptRef.current)
|
|
4127
4383
|
return;
|
|
@@ -4132,24 +4388,28 @@ function SessionChat({ session, initialPrompt }) {
|
|
|
4132
4388
|
model: initialPrompt.model
|
|
4133
4389
|
});
|
|
4134
4390
|
}, [initialPrompt, submit]);
|
|
4135
|
-
return /* @__PURE__ */
|
|
4391
|
+
return /* @__PURE__ */ jsxDEV28(SessionShell, {
|
|
4136
4392
|
onSubmit: (text) => {
|
|
4137
4393
|
deactivateQuestionPrompts();
|
|
4138
4394
|
submit({ userText: text, mode, model });
|
|
4139
4395
|
},
|
|
4140
4396
|
loading: status === "submitted" || status === "streaming",
|
|
4141
4397
|
interruptible: status === "submitted" || status === "streaming",
|
|
4398
|
+
inputDisabled: status === "submitted" || status === "streaming" || questionPrompts.some((p) => p.isActive) || pendingConfirmations.length > 0,
|
|
4142
4399
|
children: [
|
|
4143
4400
|
messages.map((msg, i) => {
|
|
4144
4401
|
const isLastAssistant = msg.role === "assistant" && i === messages.length - 1;
|
|
4145
|
-
return /* @__PURE__ */
|
|
4402
|
+
return /* @__PURE__ */ jsxDEV28(ChatMessage, {
|
|
4146
4403
|
msg,
|
|
4147
4404
|
questionPrompts,
|
|
4148
4405
|
onSubmitQuestionAnswer: submitQuestionAnswer,
|
|
4406
|
+
pendingConfirmations,
|
|
4407
|
+
onAllowConfirmation: allowConfirmation,
|
|
4408
|
+
onDisallowConfirmation: disallowConfirmation,
|
|
4149
4409
|
isStreaming: isLastAssistant && status === "streaming"
|
|
4150
4410
|
}, msg.id, false, undefined, this);
|
|
4151
4411
|
}),
|
|
4152
|
-
error && /* @__PURE__ */
|
|
4412
|
+
error && /* @__PURE__ */ jsxDEV28(ErrorMessage, {
|
|
4153
4413
|
message: error.message
|
|
4154
4414
|
}, undefined, false, undefined, this)
|
|
4155
4415
|
]
|
|
@@ -4199,34 +4459,34 @@ function Session() {
|
|
|
4199
4459
|
};
|
|
4200
4460
|
}, [id, prefetched, toast, navigate]);
|
|
4201
4461
|
if (!session) {
|
|
4202
|
-
return /* @__PURE__ */
|
|
4462
|
+
return /* @__PURE__ */ jsxDEV28(SessionShell, {
|
|
4203
4463
|
onSubmit: () => {},
|
|
4204
4464
|
inputDisabled: true,
|
|
4205
4465
|
loading: true
|
|
4206
4466
|
}, undefined, false, undefined, this);
|
|
4207
4467
|
}
|
|
4208
|
-
return /* @__PURE__ */
|
|
4468
|
+
return /* @__PURE__ */ jsxDEV28(SessionChat, {
|
|
4209
4469
|
session,
|
|
4210
4470
|
initialPrompt: prefetched?.initialPrompt
|
|
4211
4471
|
}, session.id, false, undefined, this);
|
|
4212
4472
|
}
|
|
4213
4473
|
|
|
4214
4474
|
// src/index.tsx
|
|
4215
|
-
import { jsxDEV as
|
|
4475
|
+
import { jsxDEV as jsxDEV29 } from "@opentui/react/jsx-dev-runtime";
|
|
4216
4476
|
var router = createMemoryRouter([
|
|
4217
4477
|
{
|
|
4218
4478
|
path: "/",
|
|
4219
|
-
element: /* @__PURE__ */
|
|
4479
|
+
element: /* @__PURE__ */ jsxDEV29(RootLayout, {}, undefined, false, undefined, this),
|
|
4220
4480
|
children: [
|
|
4221
|
-
{ index: true, element: /* @__PURE__ */
|
|
4222
|
-
{ path: "sessions/new", element: /* @__PURE__ */
|
|
4223
|
-
{ path: "sessions/:id", element: /* @__PURE__ */
|
|
4224
|
-
{ path: "docs", element: /* @__PURE__ */
|
|
4481
|
+
{ index: true, element: /* @__PURE__ */ jsxDEV29(Home, {}, undefined, false, undefined, this) },
|
|
4482
|
+
{ path: "sessions/new", element: /* @__PURE__ */ jsxDEV29(NewSession, {}, undefined, false, undefined, this) },
|
|
4483
|
+
{ path: "sessions/:id", element: /* @__PURE__ */ jsxDEV29(Session, {}, undefined, false, undefined, this) },
|
|
4484
|
+
{ path: "docs", element: /* @__PURE__ */ jsxDEV29(Docs, {}, undefined, false, undefined, this) }
|
|
4225
4485
|
]
|
|
4226
4486
|
}
|
|
4227
4487
|
]);
|
|
4228
4488
|
function App() {
|
|
4229
|
-
return /* @__PURE__ */
|
|
4489
|
+
return /* @__PURE__ */ jsxDEV29(RouterProvider, {
|
|
4230
4490
|
router
|
|
4231
4491
|
}, undefined, false, undefined, this);
|
|
4232
4492
|
}
|
|
@@ -4234,4 +4494,4 @@ var renderer = await createCliRenderer({
|
|
|
4234
4494
|
targetFps: 60,
|
|
4235
4495
|
exitOnCtrlC: false
|
|
4236
4496
|
});
|
|
4237
|
-
createRoot(renderer).render(/* @__PURE__ */
|
|
4497
|
+
createRoot(renderer).render(/* @__PURE__ */ jsxDEV29(App, {}, undefined, false, undefined, this));
|