minimal-agent 0.1.2 → 0.1.4
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/main.js +136 -60
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -4,6 +4,19 @@
|
|
|
4
4
|
import { render } from "ink";
|
|
5
5
|
import { createRequire } from "module";
|
|
6
6
|
|
|
7
|
+
// src/bootstrap/workingDir.ts
|
|
8
|
+
import { resolve } from "path";
|
|
9
|
+
var _workingDir = null;
|
|
10
|
+
function initWorkingDir() {
|
|
11
|
+
if (_workingDir !== null) return _workingDir;
|
|
12
|
+
const override = process.env.MINIMAL_AGENT_CWD;
|
|
13
|
+
_workingDir = resolve(override ?? process.cwd());
|
|
14
|
+
return _workingDir;
|
|
15
|
+
}
|
|
16
|
+
function getWorkingDir() {
|
|
17
|
+
return _workingDir ?? initWorkingDir();
|
|
18
|
+
}
|
|
19
|
+
|
|
7
20
|
// src/config/configFile.ts
|
|
8
21
|
import { chmod, mkdir, readFile, writeFile } from "fs/promises";
|
|
9
22
|
import { homedir } from "os";
|
|
@@ -111,16 +124,51 @@ async function loadProviderLayered() {
|
|
|
111
124
|
}
|
|
112
125
|
|
|
113
126
|
// src/context/persistContext.ts
|
|
114
|
-
import { mkdir as
|
|
127
|
+
import { mkdir as mkdir3, readFile as readFile2, unlink, writeFile as writeFile2 } from "fs/promises";
|
|
128
|
+
import { dirname as dirname3 } from "path";
|
|
129
|
+
|
|
130
|
+
// src/context/sessionPath.ts
|
|
131
|
+
import { createHash } from "crypto";
|
|
132
|
+
import { mkdir as mkdir2, rename, stat } from "fs/promises";
|
|
115
133
|
import { homedir as homedir2 } from "os";
|
|
116
|
-
import { dirname as dirname2, join as join2 } from "path";
|
|
134
|
+
import { dirname as dirname2, join as join2, resolve as resolve2 } from "path";
|
|
135
|
+
function sessionFileFor(cwd) {
|
|
136
|
+
const normalized = resolve2(cwd).replace(/\\/g, "/").toLowerCase();
|
|
137
|
+
const sanitized = normalized.replace(/:/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
|
|
138
|
+
const hash = createHash("sha1").update(normalized).digest("hex").slice(0, 6);
|
|
139
|
+
return join2(
|
|
140
|
+
homedir2(),
|
|
141
|
+
".minimal-agent",
|
|
142
|
+
"sessions",
|
|
143
|
+
`${sanitized}-${hash}.json`
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
async function migrateLegacyContext(cwd) {
|
|
147
|
+
const legacy = join2(homedir2(), ".minimal-agent", "last-context.json");
|
|
148
|
+
try {
|
|
149
|
+
await stat(legacy);
|
|
150
|
+
} catch {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
const target = sessionFileFor(cwd);
|
|
154
|
+
try {
|
|
155
|
+
await mkdir2(dirname2(target), { recursive: true });
|
|
156
|
+
await rename(legacy, target);
|
|
157
|
+
} catch {
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// src/context/persistContext.ts
|
|
117
162
|
function getContextPath() {
|
|
118
|
-
|
|
163
|
+
if (process.env.MINIMAL_AGENT_CONTEXT_FILE) {
|
|
164
|
+
return process.env.MINIMAL_AGENT_CONTEXT_FILE;
|
|
165
|
+
}
|
|
166
|
+
return sessionFileFor(getWorkingDir());
|
|
119
167
|
}
|
|
120
|
-
async function loadContext() {
|
|
121
|
-
const
|
|
168
|
+
async function loadContext(file) {
|
|
169
|
+
const target = file ?? getContextPath();
|
|
122
170
|
try {
|
|
123
|
-
const raw = await readFile2(
|
|
171
|
+
const raw = await readFile2(target, "utf8");
|
|
124
172
|
const data = JSON.parse(raw);
|
|
125
173
|
if (!Array.isArray(data.messages)) return null;
|
|
126
174
|
return data.messages;
|
|
@@ -128,19 +176,19 @@ async function loadContext() {
|
|
|
128
176
|
return null;
|
|
129
177
|
}
|
|
130
178
|
}
|
|
131
|
-
async function saveContext(messages) {
|
|
132
|
-
const
|
|
179
|
+
async function saveContext(messages, file) {
|
|
180
|
+
const target = file ?? getContextPath();
|
|
133
181
|
try {
|
|
134
|
-
await
|
|
182
|
+
await mkdir3(dirname3(target), { recursive: true });
|
|
135
183
|
const data = { updatedAt: Date.now(), messages };
|
|
136
|
-
await writeFile2(
|
|
184
|
+
await writeFile2(target, JSON.stringify(data), "utf8");
|
|
137
185
|
} catch {
|
|
138
186
|
}
|
|
139
187
|
}
|
|
140
|
-
async function clearContext() {
|
|
141
|
-
const
|
|
188
|
+
async function clearContext(file) {
|
|
189
|
+
const target = file ?? getContextPath();
|
|
142
190
|
try {
|
|
143
|
-
await unlink(
|
|
191
|
+
await unlink(target);
|
|
144
192
|
} catch {
|
|
145
193
|
}
|
|
146
194
|
}
|
|
@@ -177,20 +225,20 @@ import { join as join4 } from "path";
|
|
|
177
225
|
|
|
178
226
|
// src/utils/packageRoot.ts
|
|
179
227
|
import { existsSync } from "fs";
|
|
180
|
-
import { dirname as
|
|
228
|
+
import { dirname as dirname4, resolve as resolve3 } from "path";
|
|
181
229
|
import { fileURLToPath } from "url";
|
|
182
230
|
var cache = /* @__PURE__ */ new Map();
|
|
183
231
|
var MAX_DEPTH = 8;
|
|
184
232
|
function findPackageRoot(metaUrl) {
|
|
185
233
|
const cached2 = cache.get(metaUrl);
|
|
186
234
|
if (cached2 !== void 0) return cached2;
|
|
187
|
-
let dir =
|
|
235
|
+
let dir = dirname4(fileURLToPath(metaUrl));
|
|
188
236
|
for (let i = 0; i < MAX_DEPTH; i++) {
|
|
189
|
-
if (existsSync(
|
|
237
|
+
if (existsSync(resolve3(dir, "package.json"))) {
|
|
190
238
|
cache.set(metaUrl, dir);
|
|
191
239
|
return dir;
|
|
192
240
|
}
|
|
193
|
-
const parent =
|
|
241
|
+
const parent = dirname4(dir);
|
|
194
242
|
if (parent === dir) break;
|
|
195
243
|
dir = parent;
|
|
196
244
|
}
|
|
@@ -249,10 +297,14 @@ function formatSkillHint(skills) {
|
|
|
249
297
|
const lines = [];
|
|
250
298
|
lines.push("# \u53EF\u7528\u6280\u80FD\uFF08/\u547D\u4EE4\uFF09");
|
|
251
299
|
lines.push("");
|
|
300
|
+
lines.push(`> Skills \u6839\u76EE\u5F55\u7EDD\u5BF9\u8DEF\u5F84\uFF1A\`${SKILLS_DIR}\``);
|
|
301
|
+
lines.push("");
|
|
252
302
|
lines.push(
|
|
253
303
|
"\u4EE5\u4E0B\u662F\u5F53\u524D\u53EF\u7528\u7684\u6280\u80FD\u3002**\u5F53\u7528\u6237\u610F\u56FE\u5339\u914D\u67D0\u4E2A\u6280\u80FD\u7684\u89E6\u53D1\u65F6\u673A\u65F6\uFF0C\u4F60\u5E94\u8BE5\u4E3B\u52A8\u4F7F\u7528\u5B83**\u3002"
|
|
254
304
|
);
|
|
255
|
-
lines.push(
|
|
305
|
+
lines.push(
|
|
306
|
+
`\u5728\u4F7F\u7528\u524D\uFF0C\u5148\u7528 Read \u5DE5\u5177\u8BFB\u53D6 \`${SKILLS_DIR}/{name}/SKILL.md\` \u4E86\u89E3\u5B8C\u6574\u6D41\u7A0B\u3002`
|
|
307
|
+
);
|
|
256
308
|
lines.push("");
|
|
257
309
|
for (const skill of skills) {
|
|
258
310
|
const type = skill.type ?? "prompt\uFF08\u5C55\u5F00\u4E3A\u7CFB\u7EDF\u63D0\u793A\u8BCD\uFF0C\u6307\u5BFC\u6A21\u578B\u6267\u884C\u590D\u6742\u4EFB\u52A1\uFF09";
|
|
@@ -261,15 +313,17 @@ function formatSkillHint(skills) {
|
|
|
261
313
|
lines.push(`- **\u89E6\u53D1\u65F6\u673A**: ${triggers}`);
|
|
262
314
|
lines.push(`- **\u529F\u80FD**: ${skill.description}`);
|
|
263
315
|
lines.push(`- **\u7C7B\u578B**: ${type}`);
|
|
316
|
+
lines.push(`- **\u6280\u80FD\u76EE\u5F55**: \`${SKILLS_DIR}/${skill.name}/\``);
|
|
264
317
|
lines.push("");
|
|
265
318
|
}
|
|
266
319
|
lines.push("## \u6280\u80FD\u8C03\u7528\u6D41\u7A0B");
|
|
267
320
|
lines.push("");
|
|
268
321
|
lines.push("```");
|
|
269
322
|
lines.push("1. \u5728 T \u9636\u6BB5\u5224\u65AD\u7528\u6237\u610F\u56FE\u662F\u5426\u5339\u914D\u67D0\u4E2A\u6280\u80FD\u7684\u89E6\u53D1\u65F6\u673A");
|
|
270
|
-
lines.push(
|
|
323
|
+
lines.push(`2. \u5339\u914D \u2192 \u5728 A \u9636\u6BB5\u7528 Read \u5DE5\u5177\u8BFB\u53D6 ${SKILLS_DIR}/{name}/SKILL.md`);
|
|
271
324
|
lines.push("3. \u6309\u7167 SKILL.md \u7684 Quick Reference \u548C\u6D41\u7A0B\u6267\u884C");
|
|
272
|
-
lines.push("4. \
|
|
325
|
+
lines.push("4. \u6280\u80FD\u811A\u672C\uFF08scripts/\uFF09\u4E0E SKILL.md \u4F4D\u4E8E\u540C\u4E00\u76EE\u5F55\u4E0B\uFF0C\u7528\u7EDD\u5BF9\u8DEF\u5F84\u6267\u884C");
|
|
326
|
+
lines.push("5. \u5982\u679C\u6280\u80FD\u7C7B\u578B\u662F prompt\uFF0C\u5C06\u5176\u5185\u5BB9\u4F5C\u4E3A\u989D\u5916\u4E0A\u4E0B\u6587\u6307\u5BFC\u540E\u7EED\u64CD\u4F5C");
|
|
273
327
|
lines.push("```");
|
|
274
328
|
lines.push("");
|
|
275
329
|
lines.push("> \u{1F4A1} \u6280\u80FD\u662F\u5DE5\u5177\u7684\u7EC4\u5408\u62F3\u3002\u5355\u4E2A\u5DE5\u5177\u662F\u57FA\u7840\u64CD\u4F5C\uFF1B\u6280\u80FD\u662F\u9488\u5BF9\u7279\u5B9A\u573A\u666F\u7684\u6807\u51C6\u5316\u5DE5\u4F5C\u6D41\u3002");
|
|
@@ -561,7 +615,7 @@ async function call(input, signal) {
|
|
|
561
615
|
await new Promise((resolveP, rejectP) => {
|
|
562
616
|
const child = spawn(command, {
|
|
563
617
|
shell: true,
|
|
564
|
-
cwd:
|
|
618
|
+
cwd: getWorkingDir(),
|
|
565
619
|
signal: ac.signal,
|
|
566
620
|
env: process.env,
|
|
567
621
|
windowsHide: true
|
|
@@ -639,9 +693,9 @@ var bashTool = {
|
|
|
639
693
|
};
|
|
640
694
|
|
|
641
695
|
// src/tools/edit/edit.ts
|
|
642
|
-
import { readFile as readFile5, writeFile as writeFile3, mkdir as
|
|
696
|
+
import { readFile as readFile5, writeFile as writeFile3, mkdir as mkdir4 } from "fs/promises";
|
|
643
697
|
import { existsSync as existsSync2 } from "fs";
|
|
644
|
-
import { dirname as
|
|
698
|
+
import { dirname as dirname5, resolve as resolve4 } from "path";
|
|
645
699
|
import { z as z2 } from "zod";
|
|
646
700
|
var MAX_EDIT_FILE_SIZE_BYTES = 1024 * 1024 * 1024;
|
|
647
701
|
var inputSchema2 = z2.object({
|
|
@@ -674,7 +728,7 @@ function validatePath(filePath) {
|
|
|
674
728
|
return { ok: true };
|
|
675
729
|
}
|
|
676
730
|
async function call2(input) {
|
|
677
|
-
const filePath =
|
|
731
|
+
const filePath = resolve4(input.file_path);
|
|
678
732
|
const { old_string, new_string } = input;
|
|
679
733
|
const replaceAll = input.replace_all ?? false;
|
|
680
734
|
const pathCheck = validatePath(filePath);
|
|
@@ -684,7 +738,7 @@ async function call2(input) {
|
|
|
684
738
|
}
|
|
685
739
|
if (old_string === "" && !existsSync2(filePath)) {
|
|
686
740
|
try {
|
|
687
|
-
await
|
|
741
|
+
await mkdir4(dirname5(filePath), { recursive: true });
|
|
688
742
|
await writeFile3(filePath, new_string, "utf8");
|
|
689
743
|
return {
|
|
690
744
|
ok: true,
|
|
@@ -839,8 +893,8 @@ var editTool = {
|
|
|
839
893
|
};
|
|
840
894
|
|
|
841
895
|
// src/tools/glob/glob.ts
|
|
842
|
-
import { stat } from "fs/promises";
|
|
843
|
-
import { isAbsolute, resolve as
|
|
896
|
+
import { stat as stat2 } from "fs/promises";
|
|
897
|
+
import { isAbsolute, resolve as resolve5 } from "path";
|
|
844
898
|
import fg from "fast-glob";
|
|
845
899
|
import { z as z3 } from "zod";
|
|
846
900
|
var inputSchema3 = z3.object({
|
|
@@ -854,7 +908,7 @@ var description3 = `- Fast file pattern matching tool that works with any codeba
|
|
|
854
908
|
- Use this tool when you need to find files by name patterns
|
|
855
909
|
- When you need to do an open ended search that may require multiple rounds, prefer the Grep tool for content search`;
|
|
856
910
|
async function call3(input) {
|
|
857
|
-
const cwd = input.path ?
|
|
911
|
+
const cwd = input.path ? resolve5(input.path) : getWorkingDir();
|
|
858
912
|
const pattern = input.pattern.replace(/\\/g, "/");
|
|
859
913
|
let matches;
|
|
860
914
|
try {
|
|
@@ -875,9 +929,9 @@ async function call3(input) {
|
|
|
875
929
|
}
|
|
876
930
|
const withMtime = await Promise.all(
|
|
877
931
|
matches.map(async (rel) => {
|
|
878
|
-
const abs = isAbsolute(rel) ? rel :
|
|
932
|
+
const abs = isAbsolute(rel) ? rel : resolve5(cwd, rel);
|
|
879
933
|
try {
|
|
880
|
-
const st = await
|
|
934
|
+
const st = await stat2(abs);
|
|
881
935
|
return { path: rel, mtime: st.mtimeMs };
|
|
882
936
|
} catch {
|
|
883
937
|
return { path: rel, mtime: 0 };
|
|
@@ -911,13 +965,13 @@ var globTool = {
|
|
|
911
965
|
|
|
912
966
|
// src/tools/grep/grep.ts
|
|
913
967
|
import { spawn as spawn3 } from "child_process";
|
|
914
|
-
import { resolve as
|
|
968
|
+
import { resolve as resolve7 } from "path";
|
|
915
969
|
import { z as z4 } from "zod";
|
|
916
970
|
|
|
917
971
|
// src/tools/grep/rgPath.ts
|
|
918
972
|
import { spawn as spawn2 } from "child_process";
|
|
919
973
|
import { chmodSync, existsSync as existsSync3 } from "fs";
|
|
920
|
-
import { resolve as
|
|
974
|
+
import { resolve as resolve6 } from "path";
|
|
921
975
|
var cached;
|
|
922
976
|
async function resolveRgPath() {
|
|
923
977
|
if (cached !== void 0) return cached;
|
|
@@ -944,7 +998,7 @@ async function detect() {
|
|
|
944
998
|
function vendoredRgPath() {
|
|
945
999
|
try {
|
|
946
1000
|
const projectRoot = findPackageRoot(import.meta.url);
|
|
947
|
-
return
|
|
1001
|
+
return resolve6(projectRoot, "vendor", "ripgrep", subdir(), exeName());
|
|
948
1002
|
} catch {
|
|
949
1003
|
return null;
|
|
950
1004
|
}
|
|
@@ -1003,26 +1057,26 @@ function claudeCodeCandidates() {
|
|
|
1003
1057
|
const npmRoots = [];
|
|
1004
1058
|
if (platform === "win32") {
|
|
1005
1059
|
if (process.env.APPDATA) {
|
|
1006
|
-
npmRoots.push(
|
|
1060
|
+
npmRoots.push(resolve6(process.env.APPDATA, "npm", "node_modules"));
|
|
1007
1061
|
}
|
|
1008
1062
|
if (process.env.USERPROFILE) {
|
|
1009
1063
|
npmRoots.push(
|
|
1010
|
-
|
|
1064
|
+
resolve6(process.env.USERPROFILE, "AppData", "Roaming", "npm", "node_modules")
|
|
1011
1065
|
);
|
|
1012
1066
|
}
|
|
1013
1067
|
} else {
|
|
1014
1068
|
const home = process.env.HOME ?? "";
|
|
1015
1069
|
if (home) {
|
|
1016
|
-
npmRoots.push(
|
|
1017
|
-
npmRoots.push(
|
|
1018
|
-
npmRoots.push(
|
|
1070
|
+
npmRoots.push(resolve6(home, ".npm-global", "lib", "node_modules"));
|
|
1071
|
+
npmRoots.push(resolve6(home, ".npm", "lib", "node_modules"));
|
|
1072
|
+
npmRoots.push(resolve6(home, "node_modules"));
|
|
1019
1073
|
}
|
|
1020
1074
|
npmRoots.push("/usr/local/lib/node_modules");
|
|
1021
1075
|
npmRoots.push("/usr/lib/node_modules");
|
|
1022
1076
|
npmRoots.push("/opt/homebrew/lib/node_modules");
|
|
1023
1077
|
}
|
|
1024
1078
|
return npmRoots.map(
|
|
1025
|
-
(root) =>
|
|
1079
|
+
(root) => resolve6(root, "@anthropic-ai", "claude-code", "vendor", "ripgrep", subdir2, exe)
|
|
1026
1080
|
);
|
|
1027
1081
|
}
|
|
1028
1082
|
|
|
@@ -1068,7 +1122,7 @@ async function call4(input, signal) {
|
|
|
1068
1122
|
args.push("--max-columns-preview");
|
|
1069
1123
|
args.push("--sort", "modified");
|
|
1070
1124
|
args.push("-e", input.pattern);
|
|
1071
|
-
args.push(input.path ?
|
|
1125
|
+
args.push(input.path ? resolve7(input.path) : ".");
|
|
1072
1126
|
const rgPath = await resolveRgPath();
|
|
1073
1127
|
if (!rgPath) {
|
|
1074
1128
|
return {
|
|
@@ -1082,7 +1136,7 @@ async function call4(input, signal) {
|
|
|
1082
1136
|
try {
|
|
1083
1137
|
await new Promise((resolveP, rejectP) => {
|
|
1084
1138
|
const child = spawn3(rgPath, args, {
|
|
1085
|
-
cwd:
|
|
1139
|
+
cwd: getWorkingDir(),
|
|
1086
1140
|
signal,
|
|
1087
1141
|
windowsHide: true
|
|
1088
1142
|
});
|
|
@@ -1136,8 +1190,8 @@ var grepTool = {
|
|
|
1136
1190
|
};
|
|
1137
1191
|
|
|
1138
1192
|
// src/tools/read/read.ts
|
|
1139
|
-
import { readFile as readFile6, stat as
|
|
1140
|
-
import { resolve as
|
|
1193
|
+
import { readFile as readFile6, stat as stat3 } from "fs/promises";
|
|
1194
|
+
import { resolve as resolve8 } from "path";
|
|
1141
1195
|
import { z as z5 } from "zod";
|
|
1142
1196
|
var inputSchema5 = z5.object({
|
|
1143
1197
|
file_path: z5.string().min(1, "\u5FC5\u987B\u63D0\u4F9B file_path").describe("\u8981\u8BFB\u53D6\u7684\u6587\u4EF6\u8DEF\u5F84\uFF0C\u7EDD\u5BF9\u8DEF\u5F84\u4F18\u5148"),
|
|
@@ -1156,12 +1210,12 @@ Usage:
|
|
|
1156
1210
|
- This tool can only read text files, not directories. To read a directory, use the Glob tool.
|
|
1157
1211
|
- If you read a file that exists but has empty contents you will receive a warning in place of file contents.`;
|
|
1158
1212
|
async function call5(input) {
|
|
1159
|
-
const filePath =
|
|
1213
|
+
const filePath = resolve8(input.file_path);
|
|
1160
1214
|
const offset = input.offset ?? 1;
|
|
1161
1215
|
const limit = input.limit ?? MAX_LINES_TO_READ;
|
|
1162
1216
|
let st;
|
|
1163
1217
|
try {
|
|
1164
|
-
st = await
|
|
1218
|
+
st = await stat3(filePath);
|
|
1165
1219
|
} catch (e) {
|
|
1166
1220
|
return {
|
|
1167
1221
|
ok: false,
|
|
@@ -2026,8 +2080,8 @@ var webSearchTool = {
|
|
|
2026
2080
|
|
|
2027
2081
|
// src/tools/write/write.ts
|
|
2028
2082
|
import { existsSync as existsSync4 } from "fs";
|
|
2029
|
-
import { mkdir as
|
|
2030
|
-
import { dirname as
|
|
2083
|
+
import { mkdir as mkdir5, stat as stat4, writeFile as writeFile4 } from "fs/promises";
|
|
2084
|
+
import { dirname as dirname6, resolve as resolve9 } from "path";
|
|
2031
2085
|
import { z as z9 } from "zod";
|
|
2032
2086
|
var MAX_WRITE_SIZE_BYTES = 1024 * 1024 * 1024;
|
|
2033
2087
|
var inputSchema9 = z9.object({
|
|
@@ -2052,7 +2106,7 @@ function validatePath2(filePath) {
|
|
|
2052
2106
|
return { ok: true };
|
|
2053
2107
|
}
|
|
2054
2108
|
async function call9(input) {
|
|
2055
|
-
const filePath =
|
|
2109
|
+
const filePath = resolve9(input.file_path);
|
|
2056
2110
|
const pathCheck = validatePath2(filePath);
|
|
2057
2111
|
if (!pathCheck.ok) return pathCheck;
|
|
2058
2112
|
const contentSize = Buffer.byteLength(input.content, "utf8");
|
|
@@ -2063,12 +2117,12 @@ async function call9(input) {
|
|
|
2063
2117
|
};
|
|
2064
2118
|
}
|
|
2065
2119
|
try {
|
|
2066
|
-
await
|
|
2120
|
+
await mkdir5(dirname6(filePath), { recursive: true });
|
|
2067
2121
|
let originalSize = 0;
|
|
2068
2122
|
const fileExisted = existsSync4(filePath);
|
|
2069
2123
|
if (fileExisted) {
|
|
2070
2124
|
try {
|
|
2071
|
-
const st = await
|
|
2125
|
+
const st = await stat4(filePath);
|
|
2072
2126
|
originalSize = st.size;
|
|
2073
2127
|
} catch {
|
|
2074
2128
|
}
|
|
@@ -2908,6 +2962,8 @@ function MessageRow({ message }) {
|
|
|
2908
2962
|
|
|
2909
2963
|
// src/ui/StatusLine.tsx
|
|
2910
2964
|
import { Box as Box4, Text as Text4 } from "ink";
|
|
2965
|
+
import { homedir as homedir4 } from "os";
|
|
2966
|
+
import { sep } from "path";
|
|
2911
2967
|
|
|
2912
2968
|
// src/llm/client.ts
|
|
2913
2969
|
async function* chat(args) {
|
|
@@ -3299,7 +3355,11 @@ function StatusLine({ provider, history }) {
|
|
|
3299
3355
|
const usage = useTokenUsage(history, provider);
|
|
3300
3356
|
const ratio = usage.tokens / usage.threshold;
|
|
3301
3357
|
const color = ratio >= 1 ? "red" : ratio >= 0.7 ? "yellow" : "green";
|
|
3358
|
+
const cwdDisplay = shortenPath(getWorkingDir());
|
|
3302
3359
|
return /* @__PURE__ */ jsxs4(Box4, { children: [
|
|
3360
|
+
/* @__PURE__ */ jsx4(Text4, { color: "cyan", children: "cwd " }),
|
|
3361
|
+
/* @__PURE__ */ jsx4(Text4, { color: "gray", children: cwdDisplay }),
|
|
3362
|
+
/* @__PURE__ */ jsx4(Text4, { color: "gray", children: " \xB7 " }),
|
|
3303
3363
|
/* @__PURE__ */ jsxs4(Text4, { color: "gray", children: [
|
|
3304
3364
|
provider.name,
|
|
3305
3365
|
"/",
|
|
@@ -3321,6 +3381,19 @@ function fmt(n) {
|
|
|
3321
3381
|
if (n < 1e6) return `${(n / 1e3).toFixed(1)}K`;
|
|
3322
3382
|
return `${(n / 1e6).toFixed(2)}M`;
|
|
3323
3383
|
}
|
|
3384
|
+
function shortenPath(abs) {
|
|
3385
|
+
const home = homedir4();
|
|
3386
|
+
let p = abs;
|
|
3387
|
+
if (home && (p === home || p.startsWith(home + sep))) {
|
|
3388
|
+
p = "~" + p.slice(home.length);
|
|
3389
|
+
}
|
|
3390
|
+
if (p.length <= 40) return p;
|
|
3391
|
+
const parts = p.split(/[\\/]/).filter(Boolean);
|
|
3392
|
+
if (parts.length <= 3) return p;
|
|
3393
|
+
const head = p.startsWith("~") ? "~" : parts[0];
|
|
3394
|
+
const tail = parts.slice(-2).join(sep);
|
|
3395
|
+
return `${head}${sep}\u2026${sep}${tail}`;
|
|
3396
|
+
}
|
|
3324
3397
|
|
|
3325
3398
|
// src/ui/ToolStatus.tsx
|
|
3326
3399
|
import { Box as Box5, Text as Text5 } from "ink";
|
|
@@ -3472,7 +3545,7 @@ async function reactiveCompactIfApplicable(messages, provider, error) {
|
|
|
3472
3545
|
}
|
|
3473
3546
|
|
|
3474
3547
|
// src/context/microCompactLite.ts
|
|
3475
|
-
import { createHash } from "crypto";
|
|
3548
|
+
import { createHash as createHash2 } from "crypto";
|
|
3476
3549
|
var MAX_REPEAT_COUNT = 3;
|
|
3477
3550
|
var MAX_RESULT_SIZE = 4e3;
|
|
3478
3551
|
var HEAD_KEEP_CHARS = 2e3;
|
|
@@ -3524,7 +3597,7 @@ function expireOldEntries() {
|
|
|
3524
3597
|
return expired;
|
|
3525
3598
|
}
|
|
3526
3599
|
function sha1(str) {
|
|
3527
|
-
return
|
|
3600
|
+
return createHash2("sha1").update(str).digest("hex");
|
|
3528
3601
|
}
|
|
3529
3602
|
function truncateContent(content) {
|
|
3530
3603
|
const omitted = content.length - HEAD_KEEP_CHARS - TAIL_KEEP_CHARS;
|
|
@@ -3756,7 +3829,7 @@ function useChat(args) {
|
|
|
3756
3829
|
}, []);
|
|
3757
3830
|
const clearHistory = useCallback5(async () => {
|
|
3758
3831
|
if (isLoading) return;
|
|
3759
|
-
const newSystemPrompt = await buildFullSystemPrompt(
|
|
3832
|
+
const newSystemPrompt = await buildFullSystemPrompt(getWorkingDir(), ALL_TOOLS);
|
|
3760
3833
|
historyRef.current.length = 0;
|
|
3761
3834
|
historyRef.current.push({ role: "system", content: newSystemPrompt });
|
|
3762
3835
|
resetReactiveCompactState();
|
|
@@ -3933,7 +4006,7 @@ function Root({ initialProvider }) {
|
|
|
3933
4006
|
return /* @__PURE__ */ jsx7(App, { provider: phase.provider, initialHistory: phase.initialHistory });
|
|
3934
4007
|
}
|
|
3935
4008
|
async function buildInitialHistory() {
|
|
3936
|
-
const content = await buildFullSystemPrompt(
|
|
4009
|
+
const content = await buildFullSystemPrompt(getWorkingDir(), ALL_TOOLS);
|
|
3937
4010
|
const fresh = { role: "system", content };
|
|
3938
4011
|
const persisted = await loadContext();
|
|
3939
4012
|
if (!persisted || persisted.length === 0) return [fresh];
|
|
@@ -4055,13 +4128,13 @@ function handleEvent2(event, output, verbose) {
|
|
|
4055
4128
|
}
|
|
4056
4129
|
}
|
|
4057
4130
|
function readFromStdin() {
|
|
4058
|
-
return new Promise((
|
|
4131
|
+
return new Promise((resolve10) => {
|
|
4059
4132
|
let data = "";
|
|
4060
4133
|
let settled = false;
|
|
4061
4134
|
const timer = setTimeout(() => {
|
|
4062
4135
|
if (!settled) {
|
|
4063
4136
|
settled = true;
|
|
4064
|
-
|
|
4137
|
+
resolve10("");
|
|
4065
4138
|
}
|
|
4066
4139
|
}, STDIN_TIMEOUT_MS);
|
|
4067
4140
|
process.stdin.setEncoding("utf8");
|
|
@@ -4072,7 +4145,7 @@ function readFromStdin() {
|
|
|
4072
4145
|
if (!settled) {
|
|
4073
4146
|
clearTimeout(timer);
|
|
4074
4147
|
settled = true;
|
|
4075
|
-
|
|
4148
|
+
resolve10(data.trim());
|
|
4076
4149
|
}
|
|
4077
4150
|
}
|
|
4078
4151
|
process.stdin.on("data", onData);
|
|
@@ -4085,6 +4158,8 @@ import { jsx as jsx8 } from "react/jsx-runtime";
|
|
|
4085
4158
|
var require2 = createRequire(import.meta.url);
|
|
4086
4159
|
var pkg = require2("../package.json");
|
|
4087
4160
|
async function main() {
|
|
4161
|
+
initWorkingDir();
|
|
4162
|
+
await migrateLegacyContext(getWorkingDir());
|
|
4088
4163
|
const args = process.argv.slice(2);
|
|
4089
4164
|
if (args.includes("-h") || args.includes("--help")) {
|
|
4090
4165
|
printHelp();
|
|
@@ -4120,7 +4195,7 @@ ${e.message}
|
|
|
4120
4195
|
await waitUntilExit();
|
|
4121
4196
|
}
|
|
4122
4197
|
async function buildInitialHistory2() {
|
|
4123
|
-
const content = await buildFullSystemPrompt(
|
|
4198
|
+
const content = await buildFullSystemPrompt(getWorkingDir(), ALL_TOOLS);
|
|
4124
4199
|
const fresh = { role: "system", content };
|
|
4125
4200
|
const persisted = await loadContext();
|
|
4126
4201
|
if (!persisted || persisted.length === 0) return [fresh];
|
|
@@ -4141,8 +4216,9 @@ minimal-agent - \u8F7B\u91CF\u7EA7 AI \u7F16\u7A0B\u52A9\u624B
|
|
|
4141
4216
|
-h, --help \u663E\u793A\u5E2E\u52A9\u4FE1\u606F
|
|
4142
4217
|
|
|
4143
4218
|
\u4F1A\u8BDD\u8BB0\u5FC6:
|
|
4144
|
-
\u81EA\u52A8\u52A0\u8F7D / \u4FDD\u5B58
|
|
4145
|
-
|
|
4219
|
+
\u6309\u5F53\u524D\u5DE5\u4F5C\u76EE\u5F55\u9694\u79BB\uFF0C\u81EA\u52A8\u52A0\u8F7D / \u4FDD\u5B58\u5230
|
|
4220
|
+
~/.minimal-agent/sessions/<\u76EE\u5F55\u54C8\u5E0C>.json
|
|
4221
|
+
TUI \u4E0E -p \u5171\u4EAB\u540C\u4E00\u76EE\u5F55\u7684\u4E0A\u4E0B\u6587\uFF1BTUI \u4E2D\u8F93\u5165 /new \u4EC5\u6E05\u5F53\u524D\u76EE\u5F55\u7684\u4F1A\u8BDD
|
|
4146
4222
|
|
|
4147
4223
|
\u793A\u4F8B:
|
|
4148
4224
|
minimal-agent -p "\u5E2E\u6211\u5199\u4E00\u4E2A hello world"
|
package/package.json
CHANGED