miii-agent 0.1.17 → 0.1.18

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/cli.js +58 -11
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -851,26 +851,45 @@ var init_run_bash = __esm({
851
851
 
852
852
  // src/tools/grep.ts
853
853
  import { execa as execa2 } from "execa";
854
- var grep;
854
+ var bool, grep;
855
855
  var init_grep = __esm({
856
856
  "src/tools/grep.ts"() {
857
857
  "use strict";
858
858
  init_paths();
859
+ bool = (v) => v === true || String(v) === "true";
859
860
  grep = {
860
861
  name: "grep",
861
862
  description: "Search file contents for a regex pattern. Uses ripgrep if available, falls back to grep -R.",
862
863
  input_schema: {
863
864
  type: "object",
864
865
  properties: {
865
- pattern: { type: "string", description: "Regex pattern" },
866
+ pattern: { type: "string", description: "Regex pattern (literal when fixed_strings)" },
866
867
  path: { type: "string", description: "Root path to search (default cwd)" },
867
868
  glob: { type: "string", description: 'File glob filter, e.g. "*.ts"' },
868
869
  case_insensitive: { type: "boolean", description: "Case-insensitive match" },
869
- max_results: { type: "number", description: "Max matching lines (default 200)" }
870
+ max_results: { type: "number", description: "Max matching lines (default 200)" },
871
+ context: { type: "number", description: "Lines of context before & after each match" },
872
+ files_only: { type: "boolean", description: "List matching filenames only" },
873
+ type: { type: "string", description: 'ripgrep file type filter, e.g. "js" (ignored by grep fallback)' },
874
+ multiline: { type: "boolean", description: "Allow matches to span multiple lines" },
875
+ count: { type: "boolean", description: "Print count of matching lines per file" },
876
+ fixed_strings: { type: "boolean", description: "Treat pattern as literal string, not regex" }
870
877
  },
871
878
  required: ["pattern"]
872
879
  },
873
- handler: async ({ pattern, path, glob: glob2, case_insensitive, max_results }) => {
880
+ handler: async ({
881
+ pattern,
882
+ path,
883
+ glob: glob2,
884
+ case_insensitive,
885
+ max_results,
886
+ context,
887
+ files_only,
888
+ type,
889
+ multiline,
890
+ count,
891
+ fixed_strings
892
+ }) => {
874
893
  let root;
875
894
  try {
876
895
  root = confinePath(path ?? ".");
@@ -878,21 +897,37 @@ var init_grep = __esm({
878
897
  return { content: err instanceof Error ? err.message : String(err), is_error: true };
879
898
  }
880
899
  const limit = max_results ?? 200;
881
- const ci = case_insensitive === true || String(case_insensitive) === "true";
900
+ const ci = bool(case_insensitive);
901
+ const filesOnly = bool(files_only);
902
+ const ml = bool(multiline);
903
+ const cnt = bool(count);
904
+ const fixed = bool(fixed_strings);
905
+ const ctx = typeof context === "number" && context > 0 ? Math.floor(context) : 0;
882
906
  const tryRg = async () => {
883
907
  const args2 = ["--line-number", "--no-heading", "--color=never", "-m", String(limit)];
884
908
  if (ci) args2.push("-i");
909
+ if (fixed) args2.push("-F");
885
910
  if (glob2) args2.push("--glob", glob2);
911
+ if (type) args2.push("-t", type);
912
+ if (ctx) args2.push("-C", String(ctx));
913
+ if (ml) args2.push("-U", "--multiline-dotall");
914
+ if (filesOnly) args2.push("-l");
915
+ if (cnt) args2.push("-c");
886
916
  args2.push("--", pattern, root);
887
917
  return execa2("rg", args2, { reject: false, timeout: 2e4 });
888
918
  };
889
919
  const tryGrep = async () => {
890
920
  const args2 = ["-R", "-n", "--color=never"];
891
921
  if (ci) args2.push("-i");
922
+ if (fixed) args2.push("-F");
892
923
  if (glob2) args2.push("--include", glob2);
924
+ if (ctx) args2.push("-C", String(ctx));
925
+ if (filesOnly) args2.push("-l");
926
+ if (cnt) args2.push("-c");
893
927
  args2.push("--", pattern, root);
894
928
  return execa2("grep", args2, { reject: false, timeout: 2e4 });
895
929
  };
930
+ const missing = (err) => err?.code === "ENOENT" || err?.errno === "ENOENT";
896
931
  try {
897
932
  let res;
898
933
  try {
@@ -900,7 +935,8 @@ var init_grep = __esm({
900
935
  if (res.exitCode === 127 || (res.stderr ?? "").includes("command not found")) {
901
936
  res = await tryGrep();
902
937
  }
903
- } catch {
938
+ } catch (err) {
939
+ if (!missing(err)) throw err;
904
940
  res = await tryGrep();
905
941
  }
906
942
  const lines = (res.stdout ?? "").split("\n").slice(0, limit);
@@ -1148,9 +1184,19 @@ This prevents drift. Each step attends to the original goal, not just the previo
1148
1184
 
1149
1185
  # Output format
1150
1186
  - Always reply in plain text. Never use Markdown syntax: no \`#\` headings, no \`**bold**\`, no \`-\` bullet lists, no fenced \`\`\` code blocks, no inline backticks.
1187
+ - This applies to your reasoning/thinking too. Write internal thoughts in plain text \u2014 no Markdown headings, bold, lists, or code fences there either.
1151
1188
  - Quote code, paths, and identifiers inline as plain text. Do not wrap them.
1152
1189
  - Keep prose terse.
1153
1190
 
1191
+ # Tone and voice
1192
+ - Sound like a calm, caring teammate who is genuinely invested in the user's goal. Warm, steady, reassuring \u2014 never cold or robotic.
1193
+ - Lead with empathy, especially when the user is stuck, frustrated, or facing a hard bug. Acknowledge the difficulty briefly before diving in: "That's a tricky one \u2014 let's work through it together."
1194
+ - Be encouraging about the goal. Treat it as something worth caring about, and convey quiet confidence that you'll reach it together.
1195
+ - Stay honest and direct. Empathy never means hedging, sugarcoating, or hiding bad news. Deliver hard truths kindly but plainly.
1196
+ - Keep warmth lightweight: a sentence or a few words, not gushing. One genuine, human touch beats a paragraph of pleasantries.
1197
+ - Mind the user's effort and context. If something will take a while or carry risk, say so gently and set expectations.
1198
+ - Celebrate progress in passing \u2014 a fixed bug, a passing test \u2014 without slowing the work down.
1199
+
1154
1200
  # Engineering mindset
1155
1201
  - Treat every request as one of: bug, feature, or fix. Name which one before you start.
1156
1202
  - Apply first principles: decompose unclear tasks into smallest concrete sub-problems, solve each explicitly, compose the result.
@@ -1189,7 +1235,7 @@ ${toolLines}
1189
1235
  - Prefer editing existing files over creating new ones.
1190
1236
  - For edit_file, make old_str unique by including surrounding context, or set replace_all to change every occurrence.
1191
1237
  - Never invent file paths. Read, glob, or grep before editing.
1192
- - No filler, no pleasantries, no apologies.
1238
+ - No empty filler or robotic boilerplate. A brief, genuine warm touch (see Tone and voice) is welcome; hollow pleasantries and reflexive apologies are not.
1193
1239
 
1194
1240
  # Context discipline
1195
1241
  - read_file returns line numbers and accepts offset/limit. For large files, grep or glob to the relevant region first, then read only that range with offset/limit. Do not read a whole large file when you need a few functions \u2014 it wastes the context window.
@@ -2615,10 +2661,11 @@ function ToolResultBlock({ result, toolName }) {
2615
2661
  const visible = expanded ? lines : lines.slice(0, COLLAPSED_LINES);
2616
2662
  const shown = visible.map((l) => truncate2(l, MAX_LINE_WIDTH));
2617
2663
  const extra = lines.length - shown.length;
2664
+ const header = toolName === "grep" || toolName === "glob" ? summarizeResult(result, toolName) : `${lines.length} line${lines.length === 1 ? "" : "s"}`;
2618
2665
  return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", marginLeft: 2, children: [
2619
2666
  /* @__PURE__ */ jsxs9(Text9, { color: result.is_error ? "red" : void 0, dimColor: !result.is_error, children: [
2620
2667
  "\u23BF ",
2621
- summarizeResult(result, toolName)
2668
+ header
2622
2669
  ] }),
2623
2670
  shown.map((ln, i) => /* @__PURE__ */ jsx9(Box9, { marginLeft: 4, children: /* @__PURE__ */ jsx9(Text9, { color: result.is_error ? "red" : void 0, dimColor: true, children: ln || " " }) }, i)),
2624
2671
  extra > 0 && /* @__PURE__ */ jsx9(Box9, { marginLeft: 4, children: /* @__PURE__ */ jsxs9(Text9, { dimColor: true, children: [
@@ -2809,7 +2856,7 @@ function useAgentRunner(model, activeCtx) {
2809
2856
  if (busyRef.current || !model) return;
2810
2857
  busyRef.current = true;
2811
2858
  setBusy(true);
2812
- setProcessingLabel("thinking\u2026");
2859
+ setProcessingLabel("crunching\u2026");
2813
2860
  setError(null);
2814
2861
  setMessages((prev) => [...prev, { role: "user", content: text }]);
2815
2862
  setThinking(true);
@@ -2891,7 +2938,7 @@ function useAgentRunner(model, activeCtx) {
2891
2938
  case "thinking-delta": {
2892
2939
  thinkingAcc += ev.text;
2893
2940
  setThinking(true);
2894
- setProcessingLabel("thinking\u2026");
2941
+ setProcessingLabel("crunching\u2026");
2895
2942
  flushThink();
2896
2943
  break;
2897
2944
  }
@@ -2908,7 +2955,7 @@ function useAgentRunner(model, activeCtx) {
2908
2955
  is_error: ev.block.is_error
2909
2956
  });
2910
2957
  setActiveToolResults([...turnResults]);
2911
- setProcessingLabel("thinking\u2026");
2958
+ setProcessingLabel("crunching\u2026");
2912
2959
  break;
2913
2960
  }
2914
2961
  case "turn-end": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "miii-agent",
3
- "version": "0.1.17",
3
+ "version": "0.1.18",
4
4
  "description": "Terminal AI coding agent powered by Ollama",
5
5
  "type": "module",
6
6
  "bin": {