minimal-agent 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/main.js +58 -39
  2. package/package.json +1 -1
package/dist/main.js CHANGED
@@ -173,11 +173,32 @@ async function loadProjectInstructions(cwd) {
173
173
 
174
174
  // src/prompts/skillList.ts
175
175
  import { readFile as readFile4, readdir } from "fs/promises";
176
- import { join as join4, dirname as dirname3 } from "path";
176
+ import { join as join4 } from "path";
177
+
178
+ // src/utils/packageRoot.ts
179
+ import { existsSync } from "fs";
180
+ import { dirname as dirname3, resolve } from "path";
177
181
  import { fileURLToPath } from "url";
178
- var __dirname = dirname3(fileURLToPath(import.meta.url));
179
- var PROJECT_ROOT = join4(__dirname, "..", "..");
180
- var SKILLS_DIR = join4(PROJECT_ROOT, "skills");
182
+ var cache = /* @__PURE__ */ new Map();
183
+ var MAX_DEPTH = 8;
184
+ function findPackageRoot(metaUrl) {
185
+ const cached2 = cache.get(metaUrl);
186
+ if (cached2 !== void 0) return cached2;
187
+ let dir = dirname3(fileURLToPath(metaUrl));
188
+ for (let i = 0; i < MAX_DEPTH; i++) {
189
+ if (existsSync(resolve(dir, "package.json"))) {
190
+ cache.set(metaUrl, dir);
191
+ return dir;
192
+ }
193
+ const parent = dirname3(dir);
194
+ if (parent === dir) break;
195
+ dir = parent;
196
+ }
197
+ throw new Error(`packageRoot: \u627E\u4E0D\u5230 package.json\uFF08\u8D77\u70B9 ${metaUrl}\uFF09`);
198
+ }
199
+
200
+ // src/prompts/skillList.ts
201
+ var SKILLS_DIR = join4(findPackageRoot(import.meta.url), "skills");
181
202
  function stripQuotes(s) {
182
203
  const trimmed = s.trim();
183
204
  if (trimmed.startsWith('"') && trimmed.endsWith('"') || trimmed.startsWith("'") && trimmed.endsWith("'")) {
@@ -619,8 +640,8 @@ var bashTool = {
619
640
 
620
641
  // src/tools/edit/edit.ts
621
642
  import { readFile as readFile5, writeFile as writeFile3, mkdir as mkdir3 } from "fs/promises";
622
- import { existsSync } from "fs";
623
- import { dirname as dirname4, resolve } from "path";
643
+ import { existsSync as existsSync2 } from "fs";
644
+ import { dirname as dirname4, resolve as resolve2 } from "path";
624
645
  import { z as z2 } from "zod";
625
646
  var MAX_EDIT_FILE_SIZE_BYTES = 1024 * 1024 * 1024;
626
647
  var inputSchema2 = z2.object({
@@ -653,7 +674,7 @@ function validatePath(filePath) {
653
674
  return { ok: true };
654
675
  }
655
676
  async function call2(input) {
656
- const filePath = resolve(input.file_path);
677
+ const filePath = resolve2(input.file_path);
657
678
  const { old_string, new_string } = input;
658
679
  const replaceAll = input.replace_all ?? false;
659
680
  const pathCheck = validatePath(filePath);
@@ -661,7 +682,7 @@ async function call2(input) {
661
682
  if (old_string === new_string) {
662
683
  return { ok: false, error: "old_string \u4E0E new_string \u5B8C\u5168\u76F8\u540C\uFF0C\u6CA1\u6709\u53EF\u6539\u7684\u5185\u5BB9\u3002" };
663
684
  }
664
- if (old_string === "" && !existsSync(filePath)) {
685
+ if (old_string === "" && !existsSync2(filePath)) {
665
686
  try {
666
687
  await mkdir3(dirname4(filePath), { recursive: true });
667
688
  await writeFile3(filePath, new_string, "utf8");
@@ -673,7 +694,7 @@ async function call2(input) {
673
694
  return { ok: false, error: `\u521B\u5EFA\u6587\u4EF6\u5931\u8D25\uFF1A${e.message}` };
674
695
  }
675
696
  }
676
- if (!existsSync(filePath)) {
697
+ if (!existsSync2(filePath)) {
677
698
  return {
678
699
  ok: false,
679
700
  error: `\u6587\u4EF6\u4E0D\u5B58\u5728\uFF1A${filePath}
@@ -819,7 +840,7 @@ var editTool = {
819
840
 
820
841
  // src/tools/glob/glob.ts
821
842
  import { stat } from "fs/promises";
822
- import { isAbsolute, resolve as resolve2 } from "path";
843
+ import { isAbsolute, resolve as resolve3 } from "path";
823
844
  import fg from "fast-glob";
824
845
  import { z as z3 } from "zod";
825
846
  var inputSchema3 = z3.object({
@@ -833,7 +854,7 @@ var description3 = `- Fast file pattern matching tool that works with any codeba
833
854
  - Use this tool when you need to find files by name patterns
834
855
  - When you need to do an open ended search that may require multiple rounds, prefer the Grep tool for content search`;
835
856
  async function call3(input) {
836
- const cwd = input.path ? resolve2(input.path) : process.cwd();
857
+ const cwd = input.path ? resolve3(input.path) : process.cwd();
837
858
  const pattern = input.pattern.replace(/\\/g, "/");
838
859
  let matches;
839
860
  try {
@@ -854,7 +875,7 @@ async function call3(input) {
854
875
  }
855
876
  const withMtime = await Promise.all(
856
877
  matches.map(async (rel) => {
857
- const abs = isAbsolute(rel) ? rel : resolve2(cwd, rel);
878
+ const abs = isAbsolute(rel) ? rel : resolve3(cwd, rel);
858
879
  try {
859
880
  const st = await stat(abs);
860
881
  return { path: rel, mtime: st.mtimeMs };
@@ -890,14 +911,13 @@ var globTool = {
890
911
 
891
912
  // src/tools/grep/grep.ts
892
913
  import { spawn as spawn3 } from "child_process";
893
- import { resolve as resolve4 } from "path";
914
+ import { resolve as resolve5 } from "path";
894
915
  import { z as z4 } from "zod";
895
916
 
896
917
  // src/tools/grep/rgPath.ts
897
918
  import { spawn as spawn2 } from "child_process";
898
- import { chmodSync, existsSync as existsSync2 } from "fs";
899
- import { dirname as dirname5, resolve as resolve3 } from "path";
900
- import { fileURLToPath as fileURLToPath2 } from "url";
919
+ import { chmodSync, existsSync as existsSync3 } from "fs";
920
+ import { resolve as resolve4 } from "path";
901
921
  var cached;
902
922
  async function resolveRgPath() {
903
923
  if (cached !== void 0) return cached;
@@ -906,15 +926,15 @@ async function resolveRgPath() {
906
926
  }
907
927
  async function detect() {
908
928
  const fromEnv = process.env.MINIMAL_AGENT_RIPGREP_PATH;
909
- if (fromEnv && existsSync2(fromEnv)) return fromEnv;
929
+ if (fromEnv && existsSync3(fromEnv)) return fromEnv;
910
930
  const vendored = vendoredRgPath();
911
- if (vendored && existsSync2(vendored)) {
931
+ if (vendored && existsSync3(vendored)) {
912
932
  ensureExecutable(vendored);
913
933
  return vendored;
914
934
  }
915
935
  if (await trySpawn("rg")) return "rg";
916
936
  for (const candidate of claudeCodeCandidates()) {
917
- if (existsSync2(candidate)) {
937
+ if (existsSync3(candidate)) {
918
938
  ensureExecutable(candidate);
919
939
  return candidate;
920
940
  }
@@ -923,9 +943,8 @@ async function detect() {
923
943
  }
924
944
  function vendoredRgPath() {
925
945
  try {
926
- const here = dirname5(fileURLToPath2(import.meta.url));
927
- const projectRoot = resolve3(here, "..", "..");
928
- return resolve3(projectRoot, "vendor", "ripgrep", subdir(), exeName());
946
+ const projectRoot = findPackageRoot(import.meta.url);
947
+ return resolve4(projectRoot, "vendor", "ripgrep", subdir(), exeName());
929
948
  } catch {
930
949
  return null;
931
950
  }
@@ -984,26 +1003,26 @@ function claudeCodeCandidates() {
984
1003
  const npmRoots = [];
985
1004
  if (platform === "win32") {
986
1005
  if (process.env.APPDATA) {
987
- npmRoots.push(resolve3(process.env.APPDATA, "npm", "node_modules"));
1006
+ npmRoots.push(resolve4(process.env.APPDATA, "npm", "node_modules"));
988
1007
  }
989
1008
  if (process.env.USERPROFILE) {
990
1009
  npmRoots.push(
991
- resolve3(process.env.USERPROFILE, "AppData", "Roaming", "npm", "node_modules")
1010
+ resolve4(process.env.USERPROFILE, "AppData", "Roaming", "npm", "node_modules")
992
1011
  );
993
1012
  }
994
1013
  } else {
995
1014
  const home = process.env.HOME ?? "";
996
1015
  if (home) {
997
- npmRoots.push(resolve3(home, ".npm-global", "lib", "node_modules"));
998
- npmRoots.push(resolve3(home, ".npm", "lib", "node_modules"));
999
- npmRoots.push(resolve3(home, "node_modules"));
1016
+ npmRoots.push(resolve4(home, ".npm-global", "lib", "node_modules"));
1017
+ npmRoots.push(resolve4(home, ".npm", "lib", "node_modules"));
1018
+ npmRoots.push(resolve4(home, "node_modules"));
1000
1019
  }
1001
1020
  npmRoots.push("/usr/local/lib/node_modules");
1002
1021
  npmRoots.push("/usr/lib/node_modules");
1003
1022
  npmRoots.push("/opt/homebrew/lib/node_modules");
1004
1023
  }
1005
1024
  return npmRoots.map(
1006
- (root) => resolve3(root, "@anthropic-ai", "claude-code", "vendor", "ripgrep", subdir2, exe)
1025
+ (root) => resolve4(root, "@anthropic-ai", "claude-code", "vendor", "ripgrep", subdir2, exe)
1007
1026
  );
1008
1027
  }
1009
1028
 
@@ -1049,7 +1068,7 @@ async function call4(input, signal) {
1049
1068
  args.push("--max-columns-preview");
1050
1069
  args.push("--sort", "modified");
1051
1070
  args.push("-e", input.pattern);
1052
- args.push(input.path ? resolve4(input.path) : ".");
1071
+ args.push(input.path ? resolve5(input.path) : ".");
1053
1072
  const rgPath = await resolveRgPath();
1054
1073
  if (!rgPath) {
1055
1074
  return {
@@ -1118,7 +1137,7 @@ var grepTool = {
1118
1137
 
1119
1138
  // src/tools/read/read.ts
1120
1139
  import { readFile as readFile6, stat as stat2 } from "fs/promises";
1121
- import { resolve as resolve5 } from "path";
1140
+ import { resolve as resolve6 } from "path";
1122
1141
  import { z as z5 } from "zod";
1123
1142
  var inputSchema5 = z5.object({
1124
1143
  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"),
@@ -1137,7 +1156,7 @@ Usage:
1137
1156
  - This tool can only read text files, not directories. To read a directory, use the Glob tool.
1138
1157
  - If you read a file that exists but has empty contents you will receive a warning in place of file contents.`;
1139
1158
  async function call5(input) {
1140
- const filePath = resolve5(input.file_path);
1159
+ const filePath = resolve6(input.file_path);
1141
1160
  const offset = input.offset ?? 1;
1142
1161
  const limit = input.limit ?? MAX_LINES_TO_READ;
1143
1162
  let st;
@@ -2006,9 +2025,9 @@ var webSearchTool = {
2006
2025
  };
2007
2026
 
2008
2027
  // src/tools/write/write.ts
2009
- import { existsSync as existsSync3 } from "fs";
2028
+ import { existsSync as existsSync4 } from "fs";
2010
2029
  import { mkdir as mkdir4, stat as stat3, writeFile as writeFile4 } from "fs/promises";
2011
- import { dirname as dirname6, resolve as resolve6 } from "path";
2030
+ import { dirname as dirname5, resolve as resolve7 } from "path";
2012
2031
  import { z as z9 } from "zod";
2013
2032
  var MAX_WRITE_SIZE_BYTES = 1024 * 1024 * 1024;
2014
2033
  var inputSchema9 = z9.object({
@@ -2033,7 +2052,7 @@ function validatePath2(filePath) {
2033
2052
  return { ok: true };
2034
2053
  }
2035
2054
  async function call9(input) {
2036
- const filePath = resolve6(input.file_path);
2055
+ const filePath = resolve7(input.file_path);
2037
2056
  const pathCheck = validatePath2(filePath);
2038
2057
  if (!pathCheck.ok) return pathCheck;
2039
2058
  const contentSize = Buffer.byteLength(input.content, "utf8");
@@ -2044,9 +2063,9 @@ async function call9(input) {
2044
2063
  };
2045
2064
  }
2046
2065
  try {
2047
- await mkdir4(dirname6(filePath), { recursive: true });
2066
+ await mkdir4(dirname5(filePath), { recursive: true });
2048
2067
  let originalSize = 0;
2049
- const fileExisted = existsSync3(filePath);
2068
+ const fileExisted = existsSync4(filePath);
2050
2069
  if (fileExisted) {
2051
2070
  try {
2052
2071
  const st = await stat3(filePath);
@@ -4036,13 +4055,13 @@ function handleEvent2(event, output, verbose) {
4036
4055
  }
4037
4056
  }
4038
4057
  function readFromStdin() {
4039
- return new Promise((resolve7) => {
4058
+ return new Promise((resolve8) => {
4040
4059
  let data = "";
4041
4060
  let settled = false;
4042
4061
  const timer = setTimeout(() => {
4043
4062
  if (!settled) {
4044
4063
  settled = true;
4045
- resolve7("");
4064
+ resolve8("");
4046
4065
  }
4047
4066
  }, STDIN_TIMEOUT_MS);
4048
4067
  process.stdin.setEncoding("utf8");
@@ -4053,7 +4072,7 @@ function readFromStdin() {
4053
4072
  if (!settled) {
4054
4073
  clearTimeout(timer);
4055
4074
  settled = true;
4056
- resolve7(data.trim());
4075
+ resolve8(data.trim());
4057
4076
  }
4058
4077
  }
4059
4078
  process.stdin.on("data", onData);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "minimal-agent",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "最小化 Agent 系统 —— 单对话 + 9 工具 + 自动压缩 + OpenAI 兼容 + Ink TUI(学习/教学用)",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "author": "Bill Wang <leiwang0359@gmail.com>",