code-ollama 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/{tui-D2NgQSV7.js → tui-Bc6tEJF4.js} +76 -64
- package/dist/cli.js +38 -42
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { _ as
|
|
1
|
+
import { _ as USER, a as tick, c as setClearHandler, d as loadConfig, f as saveConfig, g as SYSTEM, h as ASSISTANT, i as executeTool, l as listModels, m as withSystemMessage, n as TOOLS, o as clear, p as resetSystemMessage, r as WRITE_TOOLS, s as reset, t as READ_TOOLS, u as streamChat, v as PLAN_GENERATION_INSTRUCTION, y as VERSION } from "../cli.js";
|
|
2
2
|
import { readdirSync } from "node:fs";
|
|
3
3
|
import { join, relative } from "node:path";
|
|
4
4
|
import { homedir } from "node:os";
|
|
@@ -30,11 +30,9 @@ var APPROVE = "approve";
|
|
|
30
30
|
var REJECT = "reject";
|
|
31
31
|
//#endregion
|
|
32
32
|
//#region src/constants/mode.ts
|
|
33
|
-
var
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
PLAN: "plan"
|
|
37
|
-
};
|
|
33
|
+
var SAFE = "safe";
|
|
34
|
+
var AUTO = "auto";
|
|
35
|
+
var PLAN = "plan";
|
|
38
36
|
var LABEL = {
|
|
39
37
|
safe: "Safe",
|
|
40
38
|
auto: "Auto",
|
|
@@ -97,7 +95,7 @@ var CodeBlock = memo(function CodeBlock({ code, language, role }) {
|
|
|
97
95
|
code,
|
|
98
96
|
language
|
|
99
97
|
]);
|
|
100
|
-
const isSystem = role ===
|
|
98
|
+
const isSystem = role === SYSTEM;
|
|
101
99
|
return /* @__PURE__ */ jsx(Box, {
|
|
102
100
|
flexDirection: "column",
|
|
103
101
|
borderStyle: "round",
|
|
@@ -145,9 +143,9 @@ var TURN_ABORTED_MESSAGE = [
|
|
|
145
143
|
//#region src/components/Messages/Messages.tsx
|
|
146
144
|
function getMessageColor(role) {
|
|
147
145
|
switch (role) {
|
|
148
|
-
case
|
|
149
|
-
case
|
|
150
|
-
case
|
|
146
|
+
case USER: return "black";
|
|
147
|
+
case ASSISTANT: return "cyan";
|
|
148
|
+
case SYSTEM: return "gray";
|
|
151
149
|
default: return;
|
|
152
150
|
}
|
|
153
151
|
}
|
|
@@ -192,8 +190,8 @@ function parseContent(content) {
|
|
|
192
190
|
}
|
|
193
191
|
var Message = memo(function Message({ message }) {
|
|
194
192
|
const messageColor = getMessageColor(message.role);
|
|
195
|
-
const isSystem = message.role ===
|
|
196
|
-
const isUser = message.role ===
|
|
193
|
+
const isSystem = message.role === SYSTEM;
|
|
194
|
+
const isUser = message.role === USER;
|
|
197
195
|
if (isSystem) return /* @__PURE__ */ jsx(Box, {
|
|
198
196
|
flexDirection: "column",
|
|
199
197
|
marginBottom: 1,
|
|
@@ -306,15 +304,15 @@ function SelectPromptHint({ message = "Select option", escapeLabel = "cancel" })
|
|
|
306
304
|
var options$1 = [
|
|
307
305
|
{
|
|
308
306
|
label: "Auto - Execute tools automatically",
|
|
309
|
-
value:
|
|
307
|
+
value: AUTO
|
|
310
308
|
},
|
|
311
309
|
{
|
|
312
310
|
label: "Safe - Approve each tool",
|
|
313
|
-
value:
|
|
311
|
+
value: SAFE
|
|
314
312
|
},
|
|
315
313
|
{
|
|
316
314
|
label: "Cancel - Continue planning",
|
|
317
|
-
value:
|
|
315
|
+
value: PLAN
|
|
318
316
|
}
|
|
319
317
|
];
|
|
320
318
|
function PlanApproval({ planContent, onModeChange }) {
|
|
@@ -324,7 +322,7 @@ function PlanApproval({ planContent, onModeChange }) {
|
|
|
324
322
|
onModeChange(value);
|
|
325
323
|
}, [onModeChange]),
|
|
326
324
|
onCancel: useCallback(() => {
|
|
327
|
-
onModeChange(
|
|
325
|
+
onModeChange(PLAN);
|
|
328
326
|
}, [onModeChange]),
|
|
329
327
|
children: /* @__PURE__ */ jsxs(Box, {
|
|
330
328
|
flexDirection: "column",
|
|
@@ -529,6 +527,16 @@ function getMentionMatch(input) {
|
|
|
529
527
|
query: match[2]
|
|
530
528
|
};
|
|
531
529
|
}
|
|
530
|
+
/**
|
|
531
|
+
* Sort files alphabetically within each group:
|
|
532
|
+
* 1. Non-dot files first
|
|
533
|
+
* 2. Dot files second
|
|
534
|
+
*/
|
|
535
|
+
function sortFilePaths(left, right) {
|
|
536
|
+
const isDotLeft = left.split("/").some((segment) => segment.startsWith("."));
|
|
537
|
+
if (isDotLeft !== right.split("/").some((segment) => segment.startsWith("."))) return isDotLeft ? 1 : -1;
|
|
538
|
+
return left.localeCompare(right);
|
|
539
|
+
}
|
|
532
540
|
function buildNextInput(input, filePath) {
|
|
533
541
|
const mentionMatch = getMentionMatch(input);
|
|
534
542
|
// v8 ignore next 3
|
|
@@ -559,7 +567,7 @@ function listProjectFilesFallback(rootDir) {
|
|
|
559
567
|
}
|
|
560
568
|
}
|
|
561
569
|
walk(rootDir);
|
|
562
|
-
return filePaths.sort(
|
|
570
|
+
return filePaths.sort(sortFilePaths);
|
|
563
571
|
}
|
|
564
572
|
function listProjectFilesWithRipgrep(rootDir) {
|
|
565
573
|
return new Promise((resolve, reject) => {
|
|
@@ -571,7 +579,7 @@ function listProjectFilesWithRipgrep(rootDir) {
|
|
|
571
579
|
reject(error);
|
|
572
580
|
return;
|
|
573
581
|
}
|
|
574
|
-
resolve(stdout.split("\n").map((line) => line.trim()).filter(Boolean).map(normalizePath).sort(
|
|
582
|
+
resolve(stdout.split("\n").map((line) => line.trim()).filter(Boolean).map(normalizePath).sort(sortFilePaths));
|
|
575
583
|
});
|
|
576
584
|
});
|
|
577
585
|
}
|
|
@@ -770,7 +778,7 @@ function Chat({ model, onCommand, mode, onModeChange, sessionId }) {
|
|
|
770
778
|
}, [sessionId]);
|
|
771
779
|
const buildToolResultMessage = useCallback((toolName, result) => {
|
|
772
780
|
if (result.error?.startsWith("Tool not allowed:")) return {
|
|
773
|
-
role:
|
|
781
|
+
role: SYSTEM,
|
|
774
782
|
content: [
|
|
775
783
|
`Tool ${toolName} was blocked by execution policy`,
|
|
776
784
|
ACTION_NOT_PERFORMED,
|
|
@@ -779,12 +787,12 @@ function Chat({ model, onCommand, mode, onModeChange, sessionId }) {
|
|
|
779
787
|
].join("\n")
|
|
780
788
|
};
|
|
781
789
|
return {
|
|
782
|
-
role:
|
|
790
|
+
role: SYSTEM,
|
|
783
791
|
content: `Tool ${toolName} result:\n${result.content}${result.error ? `\nError: ${result.error}` : ""}`
|
|
784
792
|
};
|
|
785
793
|
}, []);
|
|
786
794
|
const buildPlanModeCorrectionMessage = useCallback((toolName) => ({
|
|
787
|
-
role:
|
|
795
|
+
role: SYSTEM,
|
|
788
796
|
content: [
|
|
789
797
|
`Plan mode policy: ${toolName} cannot be executed during planning`,
|
|
790
798
|
ACTION_NOT_PERFORMED,
|
|
@@ -800,7 +808,7 @@ function Chat({ model, onCommand, mode, onModeChange, sessionId }) {
|
|
|
800
808
|
setStreamingMessage(null);
|
|
801
809
|
setInterruptReason(INTERRUPT_REASON.INTERRUPTED);
|
|
802
810
|
setMessages((prev) => [...prev, {
|
|
803
|
-
role:
|
|
811
|
+
role: USER,
|
|
804
812
|
content: TURN_ABORTED_MESSAGE
|
|
805
813
|
}]);
|
|
806
814
|
}, []);
|
|
@@ -808,7 +816,7 @@ function Chat({ model, onCommand, mode, onModeChange, sessionId }) {
|
|
|
808
816
|
const controller = new AbortController();
|
|
809
817
|
abortControllerRef.current = controller;
|
|
810
818
|
const assistantMessage = {
|
|
811
|
-
role:
|
|
819
|
+
role: ASSISTANT,
|
|
812
820
|
content: ""
|
|
813
821
|
};
|
|
814
822
|
let committedMessages = currentMessages;
|
|
@@ -816,7 +824,7 @@ function Chat({ model, onCommand, mode, onModeChange, sessionId }) {
|
|
|
816
824
|
const commitAssistantMessage = () => {
|
|
817
825
|
if (assistantCommitted) {
|
|
818
826
|
// v8 ignore next
|
|
819
|
-
if (committedMessages.at(-1)?.role ===
|
|
827
|
+
if (committedMessages.at(-1)?.role === "assistant") {
|
|
820
828
|
committedMessages = [...committedMessages.slice(0, -1), { ...assistantMessage }];
|
|
821
829
|
setMessages(committedMessages);
|
|
822
830
|
}
|
|
@@ -843,10 +851,10 @@ function Chat({ model, onCommand, mode, onModeChange, sessionId }) {
|
|
|
843
851
|
} else if (chunk.type === "tool_calls") for (const toolCall of chunk.tool_calls) {
|
|
844
852
|
const requiresApproval = WRITE_TOOLS.has(toolCall.function.name);
|
|
845
853
|
// v8 ignore start
|
|
846
|
-
const allowedTools = executionMode ===
|
|
854
|
+
const allowedTools = executionMode === "plan" ? READ_TOOLS : void 0;
|
|
847
855
|
// v8 ignore stop
|
|
848
856
|
const updatedMessages = commitAssistantMessage();
|
|
849
|
-
if (executionMode ===
|
|
857
|
+
if (executionMode === "safe" && requiresApproval) {
|
|
850
858
|
setPendingToolCall(toolCall);
|
|
851
859
|
setIsLoading(false);
|
|
852
860
|
return;
|
|
@@ -881,7 +889,7 @@ function Chat({ model, onCommand, mode, onModeChange, sessionId }) {
|
|
|
881
889
|
const controller = new AbortController();
|
|
882
890
|
abortControllerRef.current = controller;
|
|
883
891
|
const assistantMessage = {
|
|
884
|
-
role:
|
|
892
|
+
role: ASSISTANT,
|
|
885
893
|
content: ""
|
|
886
894
|
};
|
|
887
895
|
let committedMessages = currentMessages;
|
|
@@ -889,7 +897,7 @@ function Chat({ model, onCommand, mode, onModeChange, sessionId }) {
|
|
|
889
897
|
const commitAssistantMessage = () => {
|
|
890
898
|
if (assistantCommitted) {
|
|
891
899
|
// v8 ignore next
|
|
892
|
-
if (committedMessages.at(-1)?.role ===
|
|
900
|
+
if (committedMessages.at(-1)?.role === "assistant") {
|
|
893
901
|
committedMessages = [...committedMessages.slice(0, -1), { ...assistantMessage }];
|
|
894
902
|
setMessages(committedMessages);
|
|
895
903
|
}
|
|
@@ -934,12 +942,12 @@ function Chat({ model, onCommand, mode, onModeChange, sessionId }) {
|
|
|
934
942
|
await prewarmCodeBlocks(assistantMessage.content);
|
|
935
943
|
const researchMessages = commitAssistantMessage();
|
|
936
944
|
const planInstruction = {
|
|
937
|
-
role:
|
|
945
|
+
role: SYSTEM,
|
|
938
946
|
content: PLAN_GENERATION_INSTRUCTION
|
|
939
947
|
};
|
|
940
948
|
const planMessages = [...researchMessages, planInstruction];
|
|
941
949
|
const planAssistantMessage = {
|
|
942
|
-
role:
|
|
950
|
+
role: ASSISTANT,
|
|
943
951
|
content: ""
|
|
944
952
|
};
|
|
945
953
|
setStreamingMessage(planAssistantMessage);
|
|
@@ -984,26 +992,26 @@ function Chat({ model, onCommand, mode, onModeChange, sessionId }) {
|
|
|
984
992
|
buildToolResultMessage,
|
|
985
993
|
model
|
|
986
994
|
]);
|
|
987
|
-
const handlePlanApproval = useCallback(async (
|
|
995
|
+
const handlePlanApproval = useCallback(async (mode) => {
|
|
988
996
|
// v8 ignore next
|
|
989
997
|
if (!pendingPlan) return;
|
|
990
998
|
const { messages: planMessages } = pendingPlan;
|
|
991
999
|
setPendingPlan(null);
|
|
992
|
-
if (
|
|
993
|
-
onModeChange(
|
|
1000
|
+
if (mode === "plan") {
|
|
1001
|
+
onModeChange(PLAN);
|
|
994
1002
|
const cancelMessage = {
|
|
995
|
-
role:
|
|
1003
|
+
role: SYSTEM,
|
|
996
1004
|
content: "Continuing in Plan mode. No tools were executed."
|
|
997
1005
|
};
|
|
998
1006
|
setMessages((previousMessages) => [...previousMessages, cancelMessage]);
|
|
999
1007
|
return;
|
|
1000
1008
|
}
|
|
1001
|
-
const selectedMode =
|
|
1009
|
+
const selectedMode = mode === "auto" ? AUTO : SAFE;
|
|
1002
1010
|
onModeChange(selectedMode);
|
|
1003
1011
|
setIsLoading(true);
|
|
1004
1012
|
const executeInstruction = {
|
|
1005
|
-
role:
|
|
1006
|
-
content:
|
|
1013
|
+
role: SYSTEM,
|
|
1014
|
+
content: mode === "auto" ? "Execute the plan above. Use tools as needed without asking for further confirmation." : "Execute the plan above one step at a time. Wait for user approval before each tool call that modifies files or runs commands."
|
|
1007
1015
|
};
|
|
1008
1016
|
await processStream([...planMessages, executeInstruction], selectedMode);
|
|
1009
1017
|
}, [
|
|
@@ -1021,7 +1029,7 @@ function Chat({ model, onCommand, mode, onModeChange, sessionId }) {
|
|
|
1021
1029
|
case APPROVE: {
|
|
1022
1030
|
const result = await executeTool(toolCall.function.name, toolCall.function.arguments);
|
|
1023
1031
|
const toolResultMessage = {
|
|
1024
|
-
role:
|
|
1032
|
+
role: SYSTEM,
|
|
1025
1033
|
content: `Tool ${toolCall.function.name} result:\n${result.content}${result.error ? `\nError: ${result.error}` : ""}`
|
|
1026
1034
|
};
|
|
1027
1035
|
const newMessages = [...messages, toolResultMessage];
|
|
@@ -1031,7 +1039,7 @@ function Chat({ model, onCommand, mode, onModeChange, sessionId }) {
|
|
|
1031
1039
|
}
|
|
1032
1040
|
case REJECT:
|
|
1033
1041
|
setMessages((previousMessages) => [...previousMessages, {
|
|
1034
|
-
role:
|
|
1042
|
+
role: USER,
|
|
1035
1043
|
content: TURN_ABORTED_MESSAGE
|
|
1036
1044
|
}]);
|
|
1037
1045
|
setIsLoading(false);
|
|
@@ -1053,12 +1061,12 @@ function Chat({ model, onCommand, mode, onModeChange, sessionId }) {
|
|
|
1053
1061
|
}
|
|
1054
1062
|
setIsLoading(true);
|
|
1055
1063
|
const userMessage = {
|
|
1056
|
-
role:
|
|
1064
|
+
role: USER,
|
|
1057
1065
|
content: userContent
|
|
1058
1066
|
};
|
|
1059
1067
|
const updatedMessages = [...messages, userMessage];
|
|
1060
1068
|
setMessages(updatedMessages);
|
|
1061
|
-
if (mode ===
|
|
1069
|
+
if (mode === "plan") await processStreamReadOnly(updatedMessages);
|
|
1062
1070
|
else await processStream(updatedMessages);
|
|
1063
1071
|
}, [
|
|
1064
1072
|
messages,
|
|
@@ -1078,7 +1086,7 @@ function Chat({ model, onCommand, mode, onModeChange, sessionId }) {
|
|
|
1078
1086
|
}),
|
|
1079
1087
|
pendingPlan && /* @__PURE__ */ jsx(PlanApproval, {
|
|
1080
1088
|
planContent: pendingPlan.planContent,
|
|
1081
|
-
onModeChange:
|
|
1089
|
+
onModeChange: handlePlanApproval
|
|
1082
1090
|
}),
|
|
1083
1091
|
!pendingPlan && pendingToolCall && /* @__PURE__ */ jsx(ToolApproval, {
|
|
1084
1092
|
toolCall: pendingToolCall,
|
|
@@ -1106,9 +1114,9 @@ function Chat({ model, onCommand, mode, onModeChange, sessionId }) {
|
|
|
1106
1114
|
//#region src/components/Footer.tsx
|
|
1107
1115
|
function getModeColor(mode) {
|
|
1108
1116
|
switch (mode) {
|
|
1109
|
-
case
|
|
1110
|
-
case
|
|
1111
|
-
case
|
|
1117
|
+
case PLAN: return "blue";
|
|
1118
|
+
case AUTO: return "red";
|
|
1119
|
+
case SAFE: return "green";
|
|
1112
1120
|
// v8 ignore next
|
|
1113
1121
|
default: return;
|
|
1114
1122
|
}
|
|
@@ -1202,8 +1210,7 @@ function ModelPicker({ currentModel, onSelect, onClose }) {
|
|
|
1202
1210
|
const [options, setOptions] = useState([]);
|
|
1203
1211
|
const [error, setError] = useState(null);
|
|
1204
1212
|
useInput(async (_input, key) => {
|
|
1205
|
-
if (!options.length)
|
|
1206
|
-
if (key.return) {
|
|
1213
|
+
if (!error && options.length && key.return) {
|
|
1207
1214
|
await tick();
|
|
1208
1215
|
onClose();
|
|
1209
1216
|
}
|
|
@@ -1241,11 +1248,16 @@ function ModelPicker({ currentModel, onSelect, onClose }) {
|
|
|
1241
1248
|
}
|
|
1242
1249
|
//#endregion
|
|
1243
1250
|
//#region src/components/App.tsx
|
|
1251
|
+
var SCREEN = /* @__PURE__ */ function(SCREEN) {
|
|
1252
|
+
SCREEN["CHAT"] = "chat";
|
|
1253
|
+
SCREEN["MODEL_PICKER"] = "model-picker";
|
|
1254
|
+
return SCREEN;
|
|
1255
|
+
}(SCREEN || {});
|
|
1244
1256
|
function App() {
|
|
1245
1257
|
const { exit } = useApp();
|
|
1246
1258
|
const [model, setModel] = useState(() => loadConfig().model);
|
|
1247
|
-
const [
|
|
1248
|
-
const [mode, setMode] = useState(
|
|
1259
|
+
const [currentScreen, setScreen] = useState(SCREEN.CHAT);
|
|
1260
|
+
const [mode, setMode] = useState(SAFE);
|
|
1249
1261
|
const [sessionId, setSessionId] = useState(0);
|
|
1250
1262
|
const [isHeaderLoaded, setIsHeaderLoaded] = useState(false);
|
|
1251
1263
|
const handleHeaderLoad = useCallback(() => {
|
|
@@ -1254,12 +1266,12 @@ function App() {
|
|
|
1254
1266
|
const handleCommand = useCallback((command) => {
|
|
1255
1267
|
switch (command) {
|
|
1256
1268
|
case "/model":
|
|
1257
|
-
|
|
1269
|
+
setScreen(SCREEN.MODEL_PICKER);
|
|
1258
1270
|
break;
|
|
1259
1271
|
case "/clear":
|
|
1260
1272
|
resetSystemMessage();
|
|
1261
1273
|
clear();
|
|
1262
|
-
|
|
1274
|
+
setScreen(SCREEN.CHAT);
|
|
1263
1275
|
setSessionId((sessionId) => sessionId + 1);
|
|
1264
1276
|
break;
|
|
1265
1277
|
case "/exit":
|
|
@@ -1270,32 +1282,32 @@ function App() {
|
|
|
1270
1282
|
const handleSelect = useCallback((selected) => {
|
|
1271
1283
|
setModel(selected);
|
|
1272
1284
|
saveConfig({ model: selected });
|
|
1273
|
-
|
|
1285
|
+
setScreen(SCREEN.CHAT);
|
|
1274
1286
|
}, []);
|
|
1275
1287
|
const handleClose = useCallback(() => {
|
|
1276
|
-
|
|
1288
|
+
setScreen(SCREEN.CHAT);
|
|
1277
1289
|
}, []);
|
|
1278
1290
|
const handleToggleMode = useCallback(() => {
|
|
1279
1291
|
setMode((mode) => {
|
|
1280
1292
|
switch (mode) {
|
|
1281
|
-
case
|
|
1282
|
-
case
|
|
1283
|
-
case
|
|
1284
|
-
default: return
|
|
1293
|
+
case SAFE: return AUTO;
|
|
1294
|
+
case AUTO: return PLAN;
|
|
1295
|
+
case PLAN:
|
|
1296
|
+
default: return SAFE;
|
|
1285
1297
|
}
|
|
1286
1298
|
});
|
|
1287
1299
|
}, []);
|
|
1288
|
-
let
|
|
1289
|
-
switch (
|
|
1290
|
-
case
|
|
1291
|
-
|
|
1300
|
+
let screenContent;
|
|
1301
|
+
switch (currentScreen) {
|
|
1302
|
+
case SCREEN.MODEL_PICKER:
|
|
1303
|
+
screenContent = /* @__PURE__ */ jsx(ModelPicker, {
|
|
1292
1304
|
currentModel: model,
|
|
1293
1305
|
onSelect: handleSelect,
|
|
1294
1306
|
onClose: handleClose
|
|
1295
1307
|
});
|
|
1296
1308
|
break;
|
|
1297
|
-
|
|
1298
|
-
|
|
1309
|
+
case SCREEN.CHAT:
|
|
1310
|
+
screenContent = /* @__PURE__ */ jsx(Chat, {
|
|
1299
1311
|
model,
|
|
1300
1312
|
onCommand: handleCommand,
|
|
1301
1313
|
mode,
|
|
@@ -1311,7 +1323,7 @@ function App() {
|
|
|
1311
1323
|
model,
|
|
1312
1324
|
onLoad: handleHeaderLoad
|
|
1313
1325
|
}),
|
|
1314
|
-
isHeaderLoaded &&
|
|
1326
|
+
isHeaderLoaded && screenContent,
|
|
1315
1327
|
/* @__PURE__ */ jsx(Footer, {
|
|
1316
1328
|
mode,
|
|
1317
1329
|
model,
|
package/dist/cli.js
CHANGED
|
@@ -8,7 +8,7 @@ import { exec } from "node:child_process";
|
|
|
8
8
|
import { promisify } from "node:util";
|
|
9
9
|
//#endregion
|
|
10
10
|
//#region src/constants/package.ts
|
|
11
|
-
var VERSION = "0.
|
|
11
|
+
var VERSION = "0.11.0";
|
|
12
12
|
//#endregion
|
|
13
13
|
//#region src/constants/prompt.ts
|
|
14
14
|
var BASE_SYSTEM_PROMPT = `You are a coding assistant that helps users write, edit, and understand code. You have access to tools for reading files, writing files, running shell commands, and searching code
|
|
@@ -50,22 +50,18 @@ Only include write_file, edit_file, and run_shell tools in the checklist
|
|
|
50
50
|
If no execution is needed, answer normally`;
|
|
51
51
|
//#endregion
|
|
52
52
|
//#region src/constants/role.ts
|
|
53
|
-
var
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
SYSTEM: "system"
|
|
57
|
-
};
|
|
53
|
+
var USER = "user";
|
|
54
|
+
var ASSISTANT = "assistant";
|
|
55
|
+
var SYSTEM = "system";
|
|
58
56
|
//#endregion
|
|
59
57
|
//#region src/constants/tool.ts
|
|
60
|
-
var
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
VIEW_RANGE: "view_range"
|
|
68
|
-
};
|
|
58
|
+
var READ_FILE = "read_file";
|
|
59
|
+
var WRITE_FILE = "write_file";
|
|
60
|
+
var EDIT_FILE = "edit_file";
|
|
61
|
+
var RUN_SHELL = "run_shell";
|
|
62
|
+
var LIST_DIR = "list_dir";
|
|
63
|
+
var GREP_SEARCH = "grep_search";
|
|
64
|
+
var VIEW_RANGE = "view_range";
|
|
69
65
|
//#endregion
|
|
70
66
|
//#region src/utils/agents.ts
|
|
71
67
|
var AGENTS_FILE = "AGENTS.md";
|
|
@@ -88,7 +84,7 @@ function buildSystemPrompt() {
|
|
|
88
84
|
var systemMessage = null;
|
|
89
85
|
function createSystemMessage() {
|
|
90
86
|
return {
|
|
91
|
-
role:
|
|
87
|
+
role: SYSTEM,
|
|
92
88
|
content: buildSystemPrompt()
|
|
93
89
|
};
|
|
94
90
|
}
|
|
@@ -211,11 +207,11 @@ function defineTool(name, description, params, required) {
|
|
|
211
207
|
* Tool definitions for Ollama API
|
|
212
208
|
*/
|
|
213
209
|
var TOOLS = [
|
|
214
|
-
defineTool(
|
|
210
|
+
defineTool(READ_FILE, "Read the contents of a file at the specified path", { path: {
|
|
215
211
|
type: "string",
|
|
216
212
|
description: "The path to the file to read"
|
|
217
213
|
} }, ["path"]),
|
|
218
|
-
defineTool(
|
|
214
|
+
defineTool(WRITE_FILE, "Write content to a file at the specified path", {
|
|
219
215
|
path: {
|
|
220
216
|
type: "string",
|
|
221
217
|
description: "The path to the file to write"
|
|
@@ -225,7 +221,7 @@ var TOOLS = [
|
|
|
225
221
|
description: "The content to write to the file"
|
|
226
222
|
}
|
|
227
223
|
}, ["path", "content"]),
|
|
228
|
-
defineTool(
|
|
224
|
+
defineTool(EDIT_FILE, "Replace one exact text match in an existing file at the specified path", {
|
|
229
225
|
path: {
|
|
230
226
|
type: "string",
|
|
231
227
|
description: "The path to the file to edit"
|
|
@@ -243,15 +239,15 @@ var TOOLS = [
|
|
|
243
239
|
"oldText",
|
|
244
240
|
"newText"
|
|
245
241
|
]),
|
|
246
|
-
defineTool(
|
|
242
|
+
defineTool(RUN_SHELL, "Execute a shell command", { command: {
|
|
247
243
|
type: "string",
|
|
248
244
|
description: "The shell command to execute"
|
|
249
245
|
} }, ["command"]),
|
|
250
|
-
defineTool(
|
|
246
|
+
defineTool(LIST_DIR, "List the contents of a directory", { path: {
|
|
251
247
|
type: "string",
|
|
252
248
|
description: "The path to the directory to list"
|
|
253
249
|
} }, ["path"]),
|
|
254
|
-
defineTool(
|
|
250
|
+
defineTool(GREP_SEARCH, "Search for a pattern in files within a directory", {
|
|
255
251
|
pattern: {
|
|
256
252
|
type: "string",
|
|
257
253
|
description: "The regex pattern to search for"
|
|
@@ -261,7 +257,7 @@ var TOOLS = [
|
|
|
261
257
|
description: "The directory path to search in"
|
|
262
258
|
}
|
|
263
259
|
}, ["pattern", "path"]),
|
|
264
|
-
defineTool(
|
|
260
|
+
defineTool(VIEW_RANGE, "View a specific range of lines from a file", {
|
|
265
261
|
path: {
|
|
266
262
|
type: "string",
|
|
267
263
|
description: "The path to the file"
|
|
@@ -281,15 +277,15 @@ var TOOLS = [
|
|
|
281
277
|
])
|
|
282
278
|
];
|
|
283
279
|
var READ_TOOLS = new Set([
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
280
|
+
READ_FILE,
|
|
281
|
+
LIST_DIR,
|
|
282
|
+
GREP_SEARCH,
|
|
283
|
+
VIEW_RANGE
|
|
288
284
|
]);
|
|
289
285
|
var WRITE_TOOLS = new Set([
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
286
|
+
WRITE_FILE,
|
|
287
|
+
EDIT_FILE,
|
|
288
|
+
RUN_SHELL
|
|
293
289
|
]);
|
|
294
290
|
/**
|
|
295
291
|
* Execute a tool by name with arguments
|
|
@@ -300,13 +296,13 @@ async function executeTool(name, args, options) {
|
|
|
300
296
|
error: `Tool not allowed: ${name}`
|
|
301
297
|
};
|
|
302
298
|
switch (name) {
|
|
303
|
-
case
|
|
304
|
-
case
|
|
305
|
-
case
|
|
306
|
-
case
|
|
307
|
-
case
|
|
308
|
-
case
|
|
309
|
-
case
|
|
299
|
+
case READ_FILE: return readFile(args.path);
|
|
300
|
+
case WRITE_FILE: return writeFile(args.path, args.content);
|
|
301
|
+
case EDIT_FILE: return editFile(args.path, args.oldText, args.newText);
|
|
302
|
+
case RUN_SHELL: return runShell(args.command);
|
|
303
|
+
case LIST_DIR: return listDir(args.path);
|
|
304
|
+
case GREP_SEARCH: return await grepSearch(args.pattern, args.path);
|
|
305
|
+
case VIEW_RANGE: return viewRange(args.path, args.start, args.end);
|
|
310
306
|
default: return {
|
|
311
307
|
content: "",
|
|
312
308
|
error: `Unknown tool: ${name}`
|
|
@@ -496,14 +492,14 @@ cli.command("run <model> <prompt>", "Run a one-off prompt").action(async (model,
|
|
|
496
492
|
});
|
|
497
493
|
async function runPrompt(model, prompt) {
|
|
498
494
|
await processRunStream([createSystemMessage(), {
|
|
499
|
-
role:
|
|
495
|
+
role: USER,
|
|
500
496
|
content: prompt
|
|
501
497
|
}], model);
|
|
502
498
|
process.stdout.write("\n");
|
|
503
499
|
}
|
|
504
500
|
async function processRunStream(messages, model) {
|
|
505
501
|
const assistantMessage = {
|
|
506
|
-
role:
|
|
502
|
+
role: ASSISTANT,
|
|
507
503
|
content: ""
|
|
508
504
|
};
|
|
509
505
|
for await (const chunk of streamChat(messages, model, TOOLS)) {
|
|
@@ -515,7 +511,7 @@ async function processRunStream(messages, model) {
|
|
|
515
511
|
for (const toolCall of chunk.tool_calls) {
|
|
516
512
|
const result = await executeTool(toolCall.function.name, toolCall.function.arguments);
|
|
517
513
|
const toolResultMessage = {
|
|
518
|
-
role:
|
|
514
|
+
role: SYSTEM,
|
|
519
515
|
content: `Tool ${toolCall.function.name} result:\n${result.content}${result.error ? `\nError: ${result.error}` : ""}`
|
|
520
516
|
};
|
|
521
517
|
await processRunStream([
|
|
@@ -529,7 +525,7 @@ async function processRunStream(messages, model) {
|
|
|
529
525
|
}
|
|
530
526
|
async function main(args = process.argv.slice(2)) {
|
|
531
527
|
if (!args.length) {
|
|
532
|
-
const { renderApp } = await import("./assets/tui-
|
|
528
|
+
const { renderApp } = await import("./assets/tui-Bc6tEJF4.js");
|
|
533
529
|
reset();
|
|
534
530
|
renderApp();
|
|
535
531
|
return;
|
|
@@ -552,4 +548,4 @@ function isEntrypoint(argv1 = process.argv[1]) {
|
|
|
552
548
|
if (isEntrypoint()) main();
|
|
553
549
|
// v8 ignore stop
|
|
554
550
|
//#endregion
|
|
555
|
-
export {
|
|
551
|
+
export { USER as _, tick as a, setClearHandler as c, loadConfig as d, saveConfig as f, SYSTEM as g, ASSISTANT as h, executeTool as i, listModels as l, withSystemMessage as m, main, TOOLS as n, clear as o, resetSystemMessage as p, WRITE_TOOLS as r, reset as s, READ_TOOLS as t, streamChat as u, PLAN_GENERATION_INSTRUCTION as v, VERSION as y };
|