minimal-agent 0.1.3 → 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.
Files changed (2) hide show
  1. package/dist/main.js +133 -59
  2. 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 mkdir2, readFile as readFile2, unlink, writeFile as writeFile2 } from "fs/promises";
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
- return process.env.MINIMAL_AGENT_CONTEXT_FILE ?? join2(homedir2(), ".minimal-agent", "last-context.json");
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 file = getContextPath();
168
+ async function loadContext(file) {
169
+ const target = file ?? getContextPath();
122
170
  try {
123
- const raw = await readFile2(file, "utf8");
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 file = getContextPath();
179
+ async function saveContext(messages, file) {
180
+ const target = file ?? getContextPath();
133
181
  try {
134
- await mkdir2(dirname2(file), { recursive: true });
182
+ await mkdir3(dirname3(target), { recursive: true });
135
183
  const data = { updatedAt: Date.now(), messages };
136
- await writeFile2(file, JSON.stringify(data), "utf8");
184
+ await writeFile2(target, JSON.stringify(data), "utf8");
137
185
  } catch {
138
186
  }
139
187
  }
140
- async function clearContext() {
141
- const file = getContextPath();
188
+ async function clearContext(file) {
189
+ const target = file ?? getContextPath();
142
190
  try {
143
- await unlink(file);
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 dirname3, resolve } from "path";
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 = dirname3(fileURLToPath(metaUrl));
235
+ let dir = dirname4(fileURLToPath(metaUrl));
188
236
  for (let i = 0; i < MAX_DEPTH; i++) {
189
- if (existsSync(resolve(dir, "package.json"))) {
237
+ if (existsSync(resolve3(dir, "package.json"))) {
190
238
  cache.set(metaUrl, dir);
191
239
  return dir;
192
240
  }
193
- const parent = dirname3(dir);
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(`\u5728\u4F7F\u7528\u524D\uFF0C\u5148\u7528 Read \u5DE5\u5177\u8BFB\u53D6 \`${SKILLS_DIR}/{name}/SKILL.md\` \u4E86\u89E3\u5B8C\u6574\u6D41\u7A0B\u3002`);
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";
@@ -268,7 +320,7 @@ function formatSkillHint(skills) {
268
320
  lines.push("");
269
321
  lines.push("```");
270
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");
271
- lines.push(`2. \u5339\u914D \u2192 \u5728 A \u9636\u6BB5\u7528 Read \u5DE5\u5177\u8BFB\u53D6 \`${SKILLS_DIR}/{name}/SKILL.md\``);
323
+ lines.push(`2. \u5339\u914D \u2192 \u5728 A \u9636\u6BB5\u7528 Read \u5DE5\u5177\u8BFB\u53D6 ${SKILLS_DIR}/{name}/SKILL.md`);
272
324
  lines.push("3. \u6309\u7167 SKILL.md \u7684 Quick Reference \u548C\u6D41\u7A0B\u6267\u884C");
273
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");
274
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");
@@ -563,7 +615,7 @@ async function call(input, signal) {
563
615
  await new Promise((resolveP, rejectP) => {
564
616
  const child = spawn(command, {
565
617
  shell: true,
566
- cwd: process.cwd(),
618
+ cwd: getWorkingDir(),
567
619
  signal: ac.signal,
568
620
  env: process.env,
569
621
  windowsHide: true
@@ -641,9 +693,9 @@ var bashTool = {
641
693
  };
642
694
 
643
695
  // src/tools/edit/edit.ts
644
- import { readFile as readFile5, writeFile as writeFile3, mkdir as mkdir3 } from "fs/promises";
696
+ import { readFile as readFile5, writeFile as writeFile3, mkdir as mkdir4 } from "fs/promises";
645
697
  import { existsSync as existsSync2 } from "fs";
646
- import { dirname as dirname4, resolve as resolve2 } from "path";
698
+ import { dirname as dirname5, resolve as resolve4 } from "path";
647
699
  import { z as z2 } from "zod";
648
700
  var MAX_EDIT_FILE_SIZE_BYTES = 1024 * 1024 * 1024;
649
701
  var inputSchema2 = z2.object({
@@ -676,7 +728,7 @@ function validatePath(filePath) {
676
728
  return { ok: true };
677
729
  }
678
730
  async function call2(input) {
679
- const filePath = resolve2(input.file_path);
731
+ const filePath = resolve4(input.file_path);
680
732
  const { old_string, new_string } = input;
681
733
  const replaceAll = input.replace_all ?? false;
682
734
  const pathCheck = validatePath(filePath);
@@ -686,7 +738,7 @@ async function call2(input) {
686
738
  }
687
739
  if (old_string === "" && !existsSync2(filePath)) {
688
740
  try {
689
- await mkdir3(dirname4(filePath), { recursive: true });
741
+ await mkdir4(dirname5(filePath), { recursive: true });
690
742
  await writeFile3(filePath, new_string, "utf8");
691
743
  return {
692
744
  ok: true,
@@ -841,8 +893,8 @@ var editTool = {
841
893
  };
842
894
 
843
895
  // src/tools/glob/glob.ts
844
- import { stat } from "fs/promises";
845
- import { isAbsolute, resolve as resolve3 } from "path";
896
+ import { stat as stat2 } from "fs/promises";
897
+ import { isAbsolute, resolve as resolve5 } from "path";
846
898
  import fg from "fast-glob";
847
899
  import { z as z3 } from "zod";
848
900
  var inputSchema3 = z3.object({
@@ -856,7 +908,7 @@ var description3 = `- Fast file pattern matching tool that works with any codeba
856
908
  - Use this tool when you need to find files by name patterns
857
909
  - When you need to do an open ended search that may require multiple rounds, prefer the Grep tool for content search`;
858
910
  async function call3(input) {
859
- const cwd = input.path ? resolve3(input.path) : process.cwd();
911
+ const cwd = input.path ? resolve5(input.path) : getWorkingDir();
860
912
  const pattern = input.pattern.replace(/\\/g, "/");
861
913
  let matches;
862
914
  try {
@@ -877,9 +929,9 @@ async function call3(input) {
877
929
  }
878
930
  const withMtime = await Promise.all(
879
931
  matches.map(async (rel) => {
880
- const abs = isAbsolute(rel) ? rel : resolve3(cwd, rel);
932
+ const abs = isAbsolute(rel) ? rel : resolve5(cwd, rel);
881
933
  try {
882
- const st = await stat(abs);
934
+ const st = await stat2(abs);
883
935
  return { path: rel, mtime: st.mtimeMs };
884
936
  } catch {
885
937
  return { path: rel, mtime: 0 };
@@ -913,13 +965,13 @@ var globTool = {
913
965
 
914
966
  // src/tools/grep/grep.ts
915
967
  import { spawn as spawn3 } from "child_process";
916
- import { resolve as resolve5 } from "path";
968
+ import { resolve as resolve7 } from "path";
917
969
  import { z as z4 } from "zod";
918
970
 
919
971
  // src/tools/grep/rgPath.ts
920
972
  import { spawn as spawn2 } from "child_process";
921
973
  import { chmodSync, existsSync as existsSync3 } from "fs";
922
- import { resolve as resolve4 } from "path";
974
+ import { resolve as resolve6 } from "path";
923
975
  var cached;
924
976
  async function resolveRgPath() {
925
977
  if (cached !== void 0) return cached;
@@ -946,7 +998,7 @@ async function detect() {
946
998
  function vendoredRgPath() {
947
999
  try {
948
1000
  const projectRoot = findPackageRoot(import.meta.url);
949
- return resolve4(projectRoot, "vendor", "ripgrep", subdir(), exeName());
1001
+ return resolve6(projectRoot, "vendor", "ripgrep", subdir(), exeName());
950
1002
  } catch {
951
1003
  return null;
952
1004
  }
@@ -1005,26 +1057,26 @@ function claudeCodeCandidates() {
1005
1057
  const npmRoots = [];
1006
1058
  if (platform === "win32") {
1007
1059
  if (process.env.APPDATA) {
1008
- npmRoots.push(resolve4(process.env.APPDATA, "npm", "node_modules"));
1060
+ npmRoots.push(resolve6(process.env.APPDATA, "npm", "node_modules"));
1009
1061
  }
1010
1062
  if (process.env.USERPROFILE) {
1011
1063
  npmRoots.push(
1012
- resolve4(process.env.USERPROFILE, "AppData", "Roaming", "npm", "node_modules")
1064
+ resolve6(process.env.USERPROFILE, "AppData", "Roaming", "npm", "node_modules")
1013
1065
  );
1014
1066
  }
1015
1067
  } else {
1016
1068
  const home = process.env.HOME ?? "";
1017
1069
  if (home) {
1018
- npmRoots.push(resolve4(home, ".npm-global", "lib", "node_modules"));
1019
- npmRoots.push(resolve4(home, ".npm", "lib", "node_modules"));
1020
- npmRoots.push(resolve4(home, "node_modules"));
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"));
1021
1073
  }
1022
1074
  npmRoots.push("/usr/local/lib/node_modules");
1023
1075
  npmRoots.push("/usr/lib/node_modules");
1024
1076
  npmRoots.push("/opt/homebrew/lib/node_modules");
1025
1077
  }
1026
1078
  return npmRoots.map(
1027
- (root) => resolve4(root, "@anthropic-ai", "claude-code", "vendor", "ripgrep", subdir2, exe)
1079
+ (root) => resolve6(root, "@anthropic-ai", "claude-code", "vendor", "ripgrep", subdir2, exe)
1028
1080
  );
1029
1081
  }
1030
1082
 
@@ -1070,7 +1122,7 @@ async function call4(input, signal) {
1070
1122
  args.push("--max-columns-preview");
1071
1123
  args.push("--sort", "modified");
1072
1124
  args.push("-e", input.pattern);
1073
- args.push(input.path ? resolve5(input.path) : ".");
1125
+ args.push(input.path ? resolve7(input.path) : ".");
1074
1126
  const rgPath = await resolveRgPath();
1075
1127
  if (!rgPath) {
1076
1128
  return {
@@ -1084,7 +1136,7 @@ async function call4(input, signal) {
1084
1136
  try {
1085
1137
  await new Promise((resolveP, rejectP) => {
1086
1138
  const child = spawn3(rgPath, args, {
1087
- cwd: process.cwd(),
1139
+ cwd: getWorkingDir(),
1088
1140
  signal,
1089
1141
  windowsHide: true
1090
1142
  });
@@ -1138,8 +1190,8 @@ var grepTool = {
1138
1190
  };
1139
1191
 
1140
1192
  // src/tools/read/read.ts
1141
- import { readFile as readFile6, stat as stat2 } from "fs/promises";
1142
- import { resolve as resolve6 } from "path";
1193
+ import { readFile as readFile6, stat as stat3 } from "fs/promises";
1194
+ import { resolve as resolve8 } from "path";
1143
1195
  import { z as z5 } from "zod";
1144
1196
  var inputSchema5 = z5.object({
1145
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"),
@@ -1158,12 +1210,12 @@ Usage:
1158
1210
  - This tool can only read text files, not directories. To read a directory, use the Glob tool.
1159
1211
  - If you read a file that exists but has empty contents you will receive a warning in place of file contents.`;
1160
1212
  async function call5(input) {
1161
- const filePath = resolve6(input.file_path);
1213
+ const filePath = resolve8(input.file_path);
1162
1214
  const offset = input.offset ?? 1;
1163
1215
  const limit = input.limit ?? MAX_LINES_TO_READ;
1164
1216
  let st;
1165
1217
  try {
1166
- st = await stat2(filePath);
1218
+ st = await stat3(filePath);
1167
1219
  } catch (e) {
1168
1220
  return {
1169
1221
  ok: false,
@@ -2028,8 +2080,8 @@ var webSearchTool = {
2028
2080
 
2029
2081
  // src/tools/write/write.ts
2030
2082
  import { existsSync as existsSync4 } from "fs";
2031
- import { mkdir as mkdir4, stat as stat3, writeFile as writeFile4 } from "fs/promises";
2032
- import { dirname as dirname5, resolve as resolve7 } from "path";
2083
+ import { mkdir as mkdir5, stat as stat4, writeFile as writeFile4 } from "fs/promises";
2084
+ import { dirname as dirname6, resolve as resolve9 } from "path";
2033
2085
  import { z as z9 } from "zod";
2034
2086
  var MAX_WRITE_SIZE_BYTES = 1024 * 1024 * 1024;
2035
2087
  var inputSchema9 = z9.object({
@@ -2054,7 +2106,7 @@ function validatePath2(filePath) {
2054
2106
  return { ok: true };
2055
2107
  }
2056
2108
  async function call9(input) {
2057
- const filePath = resolve7(input.file_path);
2109
+ const filePath = resolve9(input.file_path);
2058
2110
  const pathCheck = validatePath2(filePath);
2059
2111
  if (!pathCheck.ok) return pathCheck;
2060
2112
  const contentSize = Buffer.byteLength(input.content, "utf8");
@@ -2065,12 +2117,12 @@ async function call9(input) {
2065
2117
  };
2066
2118
  }
2067
2119
  try {
2068
- await mkdir4(dirname5(filePath), { recursive: true });
2120
+ await mkdir5(dirname6(filePath), { recursive: true });
2069
2121
  let originalSize = 0;
2070
2122
  const fileExisted = existsSync4(filePath);
2071
2123
  if (fileExisted) {
2072
2124
  try {
2073
- const st = await stat3(filePath);
2125
+ const st = await stat4(filePath);
2074
2126
  originalSize = st.size;
2075
2127
  } catch {
2076
2128
  }
@@ -2910,6 +2962,8 @@ function MessageRow({ message }) {
2910
2962
 
2911
2963
  // src/ui/StatusLine.tsx
2912
2964
  import { Box as Box4, Text as Text4 } from "ink";
2965
+ import { homedir as homedir4 } from "os";
2966
+ import { sep } from "path";
2913
2967
 
2914
2968
  // src/llm/client.ts
2915
2969
  async function* chat(args) {
@@ -3301,7 +3355,11 @@ function StatusLine({ provider, history }) {
3301
3355
  const usage = useTokenUsage(history, provider);
3302
3356
  const ratio = usage.tokens / usage.threshold;
3303
3357
  const color = ratio >= 1 ? "red" : ratio >= 0.7 ? "yellow" : "green";
3358
+ const cwdDisplay = shortenPath(getWorkingDir());
3304
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 " }),
3305
3363
  /* @__PURE__ */ jsxs4(Text4, { color: "gray", children: [
3306
3364
  provider.name,
3307
3365
  "/",
@@ -3323,6 +3381,19 @@ function fmt(n) {
3323
3381
  if (n < 1e6) return `${(n / 1e3).toFixed(1)}K`;
3324
3382
  return `${(n / 1e6).toFixed(2)}M`;
3325
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
+ }
3326
3397
 
3327
3398
  // src/ui/ToolStatus.tsx
3328
3399
  import { Box as Box5, Text as Text5 } from "ink";
@@ -3474,7 +3545,7 @@ async function reactiveCompactIfApplicable(messages, provider, error) {
3474
3545
  }
3475
3546
 
3476
3547
  // src/context/microCompactLite.ts
3477
- import { createHash } from "crypto";
3548
+ import { createHash as createHash2 } from "crypto";
3478
3549
  var MAX_REPEAT_COUNT = 3;
3479
3550
  var MAX_RESULT_SIZE = 4e3;
3480
3551
  var HEAD_KEEP_CHARS = 2e3;
@@ -3526,7 +3597,7 @@ function expireOldEntries() {
3526
3597
  return expired;
3527
3598
  }
3528
3599
  function sha1(str) {
3529
- return createHash("sha1").update(str).digest("hex");
3600
+ return createHash2("sha1").update(str).digest("hex");
3530
3601
  }
3531
3602
  function truncateContent(content) {
3532
3603
  const omitted = content.length - HEAD_KEEP_CHARS - TAIL_KEEP_CHARS;
@@ -3758,7 +3829,7 @@ function useChat(args) {
3758
3829
  }, []);
3759
3830
  const clearHistory = useCallback5(async () => {
3760
3831
  if (isLoading) return;
3761
- const newSystemPrompt = await buildFullSystemPrompt(process.cwd(), ALL_TOOLS);
3832
+ const newSystemPrompt = await buildFullSystemPrompt(getWorkingDir(), ALL_TOOLS);
3762
3833
  historyRef.current.length = 0;
3763
3834
  historyRef.current.push({ role: "system", content: newSystemPrompt });
3764
3835
  resetReactiveCompactState();
@@ -3935,7 +4006,7 @@ function Root({ initialProvider }) {
3935
4006
  return /* @__PURE__ */ jsx7(App, { provider: phase.provider, initialHistory: phase.initialHistory });
3936
4007
  }
3937
4008
  async function buildInitialHistory() {
3938
- const content = await buildFullSystemPrompt(process.cwd(), ALL_TOOLS);
4009
+ const content = await buildFullSystemPrompt(getWorkingDir(), ALL_TOOLS);
3939
4010
  const fresh = { role: "system", content };
3940
4011
  const persisted = await loadContext();
3941
4012
  if (!persisted || persisted.length === 0) return [fresh];
@@ -4057,13 +4128,13 @@ function handleEvent2(event, output, verbose) {
4057
4128
  }
4058
4129
  }
4059
4130
  function readFromStdin() {
4060
- return new Promise((resolve8) => {
4131
+ return new Promise((resolve10) => {
4061
4132
  let data = "";
4062
4133
  let settled = false;
4063
4134
  const timer = setTimeout(() => {
4064
4135
  if (!settled) {
4065
4136
  settled = true;
4066
- resolve8("");
4137
+ resolve10("");
4067
4138
  }
4068
4139
  }, STDIN_TIMEOUT_MS);
4069
4140
  process.stdin.setEncoding("utf8");
@@ -4074,7 +4145,7 @@ function readFromStdin() {
4074
4145
  if (!settled) {
4075
4146
  clearTimeout(timer);
4076
4147
  settled = true;
4077
- resolve8(data.trim());
4148
+ resolve10(data.trim());
4078
4149
  }
4079
4150
  }
4080
4151
  process.stdin.on("data", onData);
@@ -4087,6 +4158,8 @@ import { jsx as jsx8 } from "react/jsx-runtime";
4087
4158
  var require2 = createRequire(import.meta.url);
4088
4159
  var pkg = require2("../package.json");
4089
4160
  async function main() {
4161
+ initWorkingDir();
4162
+ await migrateLegacyContext(getWorkingDir());
4090
4163
  const args = process.argv.slice(2);
4091
4164
  if (args.includes("-h") || args.includes("--help")) {
4092
4165
  printHelp();
@@ -4122,7 +4195,7 @@ ${e.message}
4122
4195
  await waitUntilExit();
4123
4196
  }
4124
4197
  async function buildInitialHistory2() {
4125
- const content = await buildFullSystemPrompt(process.cwd(), ALL_TOOLS);
4198
+ const content = await buildFullSystemPrompt(getWorkingDir(), ALL_TOOLS);
4126
4199
  const fresh = { role: "system", content };
4127
4200
  const persisted = await loadContext();
4128
4201
  if (!persisted || persisted.length === 0) return [fresh];
@@ -4143,8 +4216,9 @@ minimal-agent - \u8F7B\u91CF\u7EA7 AI \u7F16\u7A0B\u52A9\u624B
4143
4216
  -h, --help \u663E\u793A\u5E2E\u52A9\u4FE1\u606F
4144
4217
 
4145
4218
  \u4F1A\u8BDD\u8BB0\u5FC6:
4146
- \u81EA\u52A8\u52A0\u8F7D / \u4FDD\u5B58 ~/.minimal-agent/last-context.json
4147
- TUI \u4E0E -p \u5171\u4EAB\u540C\u4E00\u4EFD\u4E0A\u4E0B\u6587\uFF1BTUI \u4E2D\u8F93\u5165 /new \u6E05\u7A7A
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
4148
4222
 
4149
4223
  \u793A\u4F8B:
4150
4224
  minimal-agent -p "\u5E2E\u6211\u5199\u4E00\u4E2A hello world"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "minimal-agent",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "最小化 Agent 系统 —— 单对话 + 9 工具 + 自动压缩 + OpenAI 兼容 + Ink TUI(学习/教学用)",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "author": "Bill Wang <leiwang0359@gmail.com>",