flavor-code 1.3.8 → 1.3.10

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.
@@ -16,7 +16,7 @@ import {
16
16
  redactErrorText,
17
17
  transcriptReducer,
18
18
  withTimeout
19
- } from "./chunk-GAQJZBOF.js";
19
+ } from "./chunk-Y3DPUAEJ.js";
20
20
  import "./chunk-IG4Z23CL.js";
21
21
  import {
22
22
  Box_default,
@@ -4,7 +4,7 @@ import {
4
4
  message,
5
5
  redactErrorText,
6
6
  redactSecrets
7
- } from "./chunk-GAQJZBOF.js";
7
+ } from "./chunk-Y3DPUAEJ.js";
8
8
 
9
9
  // src/rpc/server.ts
10
10
  import { createInterface } from "readline";
@@ -56,6 +56,8 @@ function normalizeProviderError(error) {
56
56
  code = "context_overflow";
57
57
  } else if (status === 404 || /model.*not.?found|not.?found.*model/.test(searchable)) {
58
58
  code = "model_not_found";
59
+ } else if (status !== void 0 && status >= 500 && status <= 599) {
60
+ code = "network";
59
61
  } else if (status === void 0 && /econn|enet|socket|network|fetch failed|connection|timeout/.test(searchable)) {
60
62
  code = "network";
61
63
  }
@@ -1981,9 +1983,17 @@ var FILE_TYPE_EXTENSIONS = {
1981
1983
  python: [".py", ".pyi"],
1982
1984
  typescript: [".ts", ".tsx", ".mts", ".cts"]
1983
1985
  };
1986
+ var BooleanInput = z.preprocess((value) => {
1987
+ if (typeof value !== "string") return value;
1988
+ const normalized = value.trim().toLowerCase();
1989
+ if (normalized === "true") return true;
1990
+ if (normalized === "false") return false;
1991
+ return value;
1992
+ }, z.boolean());
1984
1993
  var GlobInput = z.object({
1985
1994
  pattern: z.string().min(1),
1986
1995
  path: z.string().min(1).describe('Workspace-relative search directory. Use JSON null, not the string "null", for the workspace root.').nullable().optional(),
1996
+ includeIgnored: BooleanInput.describe("Include files excluded by .gitignore or .ignore. Git metadata remains excluded.").nullable().optional(),
1987
1997
  limit: z.coerce.number().int().positive().max(1e5).nullable().optional()
1988
1998
  });
1989
1999
  var GrepInput = z.object({
@@ -1991,6 +2001,7 @@ var GrepInput = z.object({
1991
2001
  path: z.string().min(1).describe('Workspace-relative search path. Use JSON null, not the string "null", for the workspace root.').nullable().optional(),
1992
2002
  glob: z.string().min(1).nullable().optional(),
1993
2003
  fileType: z.enum(FILE_TYPES).nullable().optional(),
2004
+ includeIgnored: BooleanInput.describe("Include files excluded by .gitignore or .ignore. Git metadata remains excluded.").nullable().optional(),
1994
2005
  context: z.coerce.number().int().nonnegative().max(100).nullable().optional(),
1995
2006
  limit: z.coerce.number().int().positive().max(1e5).nullable().optional()
1996
2007
  });
@@ -2004,23 +2015,26 @@ function createGlobTool(workspace, options = {}) {
2004
2015
  paths: (input) => [scope(root, searchPath(input.path))],
2005
2016
  summarize: (input) => {
2006
2017
  const path = searchPath(input.path);
2007
- return path ? `pattern: "${input.pattern}" in ${path}` : `pattern: "${input.pattern}"`;
2018
+ const ignored2 = input.includeIgnored === true ? " (including ignored files)" : "";
2019
+ return (path ? `pattern: "${input.pattern}" in ${path}` : `pattern: "${input.pattern}"`) + ignored2;
2008
2020
  },
2009
2021
  execute: async (input, signal) => {
2010
2022
  const limit = input.limit ?? options.defaultLimit ?? DEFAULT_RESULT_LIMIT;
2011
2023
  const start = scope(root, searchPath(input.path));
2024
+ if (isGitMetadataPath(root, start)) return { matches: [], truncated: false };
2012
2025
  const matcher = globRegex(input.pattern);
2013
2026
  const ignoreBudget = createIgnoreBudget(resources);
2027
+ const includeIgnored = input.includeIgnored === true;
2014
2028
  let paths;
2015
2029
  if (options.forceNode === true) {
2016
- paths = await nodeFiles(root, start, signal, (path) => matcher.test(path), limit + 1, resources, ignoreBudget);
2030
+ paths = await nodeFiles(root, start, signal, (path) => matcher.test(path), limit + 1, resources, ignoreBudget, includeIgnored);
2017
2031
  } else {
2018
2032
  try {
2019
- paths = await rgFiles(root, start, input.pattern, signal, options.rgPath ?? bundledRgPath, options.rgArgsPrefix ?? [], limit + 1, options.maxSearchBytes ?? DEFAULT_MAX_SEARCH_BYTES, resources, ignoreBudget);
2033
+ paths = await rgFiles(root, start, input.pattern, signal, options.rgPath ?? bundledRgPath, options.rgArgsPrefix ?? [], limit + 1, options.maxSearchBytes ?? DEFAULT_MAX_SEARCH_BYTES, resources, ignoreBudget, includeIgnored);
2020
2034
  } catch (error) {
2021
2035
  if (signal.aborted) throw signal.reason;
2022
2036
  if (!(error instanceof SearchSpawnError) || !error.fallbackSafe) throw error;
2023
- paths = await nodeFiles(root, start, signal, (path) => matcher.test(path), limit + 1, resources, createIgnoreBudget(resources));
2037
+ paths = await nodeFiles(root, start, signal, (path) => matcher.test(path), limit + 1, resources, createIgnoreBudget(resources), includeIgnored);
2024
2038
  }
2025
2039
  }
2026
2040
  const matches = paths.filter((path) => matcher.test(path)).sort(comparePaths);
@@ -2040,24 +2054,27 @@ function createGrepTool(workspace, options = {}) {
2040
2054
  const path = searchPath(input.path);
2041
2055
  const where = path ? ` in ${path}` : "";
2042
2056
  const kind = input.fileType ? ` [${input.fileType}]` : "";
2043
- return `pattern: /${input.pattern}/${kind}${where}`;
2057
+ const ignored2 = input.includeIgnored === true ? " (including ignored files)" : "";
2058
+ return `pattern: /${input.pattern}/${kind}${where}${ignored2}`;
2044
2059
  },
2045
2060
  execute: async (input, signal) => {
2046
2061
  const expression = new RegExp(input.pattern);
2047
2062
  const limit = input.limit ?? options.defaultLimit ?? DEFAULT_RESULT_LIMIT;
2048
2063
  const context = input.context ?? 0;
2049
2064
  const start = await resolveGrepPath(root, searchPath(input.path));
2065
+ if (isGitMetadataPath(root, start)) return { matches: [], truncated: false };
2050
2066
  const ignoreBudget = createIgnoreBudget(resources);
2067
+ const includeIgnored = input.includeIgnored === true;
2051
2068
  let matches;
2052
2069
  if (options.forceNode === true) {
2053
- matches = await nodeGrep(root, start, input.glob ?? void 0, input.fileType ?? void 0, expression, context, signal, limit + 1, options.maxFileBytes ?? DEFAULT_MAX_FILE_BYTES, options.maxSearchBytes ?? DEFAULT_MAX_SEARCH_BYTES, resources, ignoreBudget);
2070
+ matches = await nodeGrep(root, start, input.glob ?? void 0, input.fileType ?? void 0, expression, context, signal, limit + 1, options.maxFileBytes ?? DEFAULT_MAX_FILE_BYTES, options.maxSearchBytes ?? DEFAULT_MAX_SEARCH_BYTES, resources, ignoreBudget, includeIgnored);
2054
2071
  } else {
2055
2072
  try {
2056
2073
  matches = await rgGrep(root, start, input, context, signal, options.rgPath ?? bundledRgPath, options.rgArgsPrefix ?? [], limit + 1, options.maxFileBytes ?? DEFAULT_MAX_FILE_BYTES, options.maxSearchBytes ?? DEFAULT_MAX_SEARCH_BYTES, resources, ignoreBudget);
2057
2074
  } catch (error) {
2058
2075
  if (signal.aborted) throw signal.reason;
2059
2076
  if (!(error instanceof SearchSpawnError) || !error.fallbackSafe) throw error;
2060
- matches = await nodeGrep(root, start, input.glob ?? void 0, input.fileType ?? void 0, expression, context, signal, limit + 1, options.maxFileBytes ?? DEFAULT_MAX_FILE_BYTES, options.maxSearchBytes ?? DEFAULT_MAX_SEARCH_BYTES, resources, createIgnoreBudget(resources));
2077
+ matches = await nodeGrep(root, start, input.glob ?? void 0, input.fileType ?? void 0, expression, context, signal, limit + 1, options.maxFileBytes ?? DEFAULT_MAX_FILE_BYTES, options.maxSearchBytes ?? DEFAULT_MAX_SEARCH_BYTES, resources, createIgnoreBudget(resources), includeIgnored);
2061
2078
  }
2062
2079
  }
2063
2080
  matches.sort(compareGrepMatches);
@@ -2065,10 +2082,10 @@ function createGrepTool(workspace, options = {}) {
2065
2082
  }
2066
2083
  };
2067
2084
  }
2068
- async function rgFiles(root, start, pattern, signal, executable, argsPrefix, limit, maxBytes, resources, ignoreBudget) {
2085
+ async function rgFiles(root, start, pattern, signal, executable, argsPrefix, limit, maxBytes, resources, ignoreBudget, includeIgnored) {
2069
2086
  const target = relative4(root, start) || ".";
2070
2087
  const matcher = globRegex(pattern);
2071
- const ignoreLayers = await collectIgnoreLayers(root, start, signal, resources, ignoreBudget);
2088
+ const ignoreLayers = includeIgnored ? [] : await collectIgnoreLayers(root, start, signal, resources, ignoreBudget);
2072
2089
  const paths = [];
2073
2090
  const parser = delimitedParser(0, (record) => {
2074
2091
  if (record.length === 0) return true;
@@ -2077,7 +2094,10 @@ async function rgFiles(root, start, pattern, signal, executable, argsPrefix, lim
2077
2094
  retainTopK(paths, path, limit, comparePaths);
2078
2095
  return true;
2079
2096
  });
2080
- const output = await runStreaming(executable, [...argsPrefix, "--files", "--null", "--sort", "path", "--hidden", "--glob", "!.git", "--glob", pattern, "--", target], root, signal, maxBytes, parser);
2097
+ const args = [...argsPrefix, "--files", "--null", "--sort", "path", "--hidden", "--glob", "!.git", "--glob", "!.git/**"];
2098
+ if (includeIgnored) args.push("--no-ignore");
2099
+ args.push("--glob", pattern, "--", target);
2100
+ const output = await runStreaming(executable, args, root, signal, maxBytes, parser);
2081
2101
  if (!output.stoppedEarly && output.code !== 0 && output.code !== 1) throw new Error(output.stderr || `ripgrep exited with ${output.code}`);
2082
2102
  parser.finish();
2083
2103
  return paths;
@@ -2087,12 +2107,13 @@ async function rgGrep(root, start, input, context, signal, executable, argsPrefi
2087
2107
  if (input.fileType !== void 0 && input.fileType !== null && typeExtensions === void 0) {
2088
2108
  throw new Error(`Unsupported file type: ${input.fileType}`);
2089
2109
  }
2090
- const args = ["--json", "--line-number", "--column", "--sort", "path", "--hidden", "--glob", "!.git", "--max-filesize", String(maxFileBytes), "--context", String(context)];
2110
+ const args = ["--json", "--line-number", "--column", "--sort", "path", "--hidden", "--glob", "!.git", "--glob", "!.git/**", "--max-filesize", String(maxFileBytes), "--context", String(context)];
2111
+ if (input.includeIgnored === true) args.push("--no-ignore");
2091
2112
  if (input.glob !== void 0 && input.glob !== null) args.push("--glob", input.glob);
2092
2113
  else for (const extension of typeExtensions ?? []) args.push("--glob", `*${extension}`);
2093
2114
  args.push("--regexp", input.pattern, "--", relative4(root, start) || ".");
2094
2115
  const matches = [];
2095
- const ignoreLayers = await collectIgnoreLayers(root, start, signal, resources, ignoreBudget);
2116
+ const ignoreLayers = input.includeIgnored === true ? [] : await collectIgnoreLayers(root, start, signal, resources, ignoreBudget);
2096
2117
  const parser = delimitedParser(10, (record) => {
2097
2118
  if (record.length === 0) return true;
2098
2119
  const event = JSON.parse(decodeUtf8(record, "ripgrep JSON"));
@@ -2147,8 +2168,8 @@ async function hydrateContext(root, matches, context, signal, maxFileBytes, maxT
2147
2168
  }
2148
2169
  }
2149
2170
  }
2150
- async function nodeGrep(root, start, glob, type, expression, context, signal, maxMatches, maxFileBytes, maxSearchBytes, resources, ignoreBudget) {
2151
- const files = await nodeFiles(root, start, signal, () => true, resources.maxDiscoveredFiles + 1, resources, ignoreBudget);
2171
+ async function nodeGrep(root, start, glob, type, expression, context, signal, maxMatches, maxFileBytes, maxSearchBytes, resources, ignoreBudget, includeIgnored) {
2172
+ const files = await nodeFiles(root, start, signal, () => true, resources.maxDiscoveredFiles + 1, resources, ignoreBudget, includeIgnored);
2152
2173
  if (files.length > resources.maxDiscoveredFiles) throw new Error(`Aggregate discovered file limit of ${resources.maxDiscoveredFiles} exceeded`);
2153
2174
  const matcher = glob === void 0 ? void 0 : globRegex(glob);
2154
2175
  const extension = type === void 0 ? void 0 : typeExtension(type);
@@ -2190,23 +2211,25 @@ async function nodeGrep(root, start, glob, type, expression, context, signal, ma
2190
2211
  }
2191
2212
  return matches;
2192
2213
  }
2193
- async function nodeFiles(root, start, signal, accept, limit, resources, ignoreBudget) {
2214
+ async function nodeFiles(root, start, signal, accept, limit, resources, ignoreBudget, includeIgnored) {
2194
2215
  const ignores = [];
2195
2216
  const output = [];
2196
2217
  const delta = relative4(root, start);
2197
2218
  const segments = delta === "" ? [] : delta.split(sep4);
2198
2219
  let ancestor = root;
2199
- for (let index = 0; index < segments.length; index += 1) {
2200
- noteIgnoreDirectory(ignoreBudget);
2201
- await loadIgnoreFiles(ancestor, normalizedRelative(root, ancestor), ignores, ignoreBudget, signal);
2202
- ancestor = resolve4(ancestor, segments[index]);
2220
+ if (!includeIgnored) {
2221
+ for (let index = 0; index < segments.length; index += 1) {
2222
+ noteIgnoreDirectory(ignoreBudget);
2223
+ await loadIgnoreFiles(ancestor, normalizedRelative(root, ancestor), ignores, ignoreBudget, signal);
2224
+ ancestor = resolve4(ancestor, segments[index]);
2225
+ }
2203
2226
  }
2204
2227
  async function walk(directory) {
2205
2228
  abort(signal);
2206
2229
  const relativeDirectory = normalizedRelative(root, directory);
2207
2230
  const ruleCount = ignores.length;
2208
2231
  noteIgnoreDirectory(ignoreBudget);
2209
- await loadIgnoreFiles(directory, relativeDirectory, ignores, ignoreBudget, signal);
2232
+ if (!includeIgnored) await loadIgnoreFiles(directory, relativeDirectory, ignores, ignoreBudget, signal);
2210
2233
  const handle = await opendir(directory);
2211
2234
  const entries = [];
2212
2235
  for await (const entry2 of handle) {
@@ -2219,7 +2242,7 @@ async function nodeFiles(root, start, signal, accept, limit, resources, ignoreBu
2219
2242
  abort(signal);
2220
2243
  const absolute = resolve4(directory, entry2.name);
2221
2244
  const path = normalizedRelative(root, absolute);
2222
- if (entry2.name === ".git" || ignored(path, entry2.isDirectory(), ignores)) continue;
2245
+ if (entry2.name === ".git" || !includeIgnored && ignored(path, entry2.isDirectory(), ignores)) continue;
2223
2246
  if (entry2.isDirectory()) await walk(absolute);
2224
2247
  else if (entry2.isFile() && accept(path)) output.push(path);
2225
2248
  if (output.length >= limit) break;
@@ -2388,6 +2411,9 @@ function normalizedRelative(root, path) {
2388
2411
  function normalizePath(path) {
2389
2412
  return path.replaceAll("\\", "/");
2390
2413
  }
2414
+ function isGitMetadataPath(root, path) {
2415
+ return normalizedRelative(root, path).split("/").some((segment) => segment.toLowerCase() === ".git");
2416
+ }
2391
2417
  function comparePaths(a, b) {
2392
2418
  return a < b ? -1 : a > b ? 1 : 0;
2393
2419
  }
@@ -13965,8 +13991,8 @@ function toolsSection(toolNames) {
13965
13991
  addToolRule(rules, toolNames, "Write", "Use `Write` to create a file only when a new file is necessary.");
13966
13992
  addToolRule(rules, toolNames, "Edit", "Use `Edit` for precise replacements in existing files. Before editing, read the file and copy `oldText` verbatim from its actual current content \u2014 exact characters matter, including quote style (full-width vs ASCII) and version strings. Include enough surrounding lines to make the match unique.");
13967
13993
  addToolRule(rules, toolNames, "ApplyPatch", "Use `ApplyPatch` only when an edit genuinely spans multiple regions of one file; hunks may relocate only when their exact context has one unique nearby match. Prefer `Edit` for a single small replacement \u2014 it is easier to get right.");
13968
- addToolRule(rules, toolNames, "Glob", "Use `Glob` to find files by path pattern instead of shell directory crawling. Confirm the exact path before reading, searching, or editing; the search scope is limited to the workspace, so never pass absolute paths outside it.");
13969
- addToolRule(rules, toolNames, "Grep", "Use `Grep` to search file contents instead of shell text-search commands.");
13994
+ addToolRule(rules, toolNames, "Glob", "Use `Glob` to find files by path pattern instead of shell directory crawling. Confirm the exact path before reading, searching, or editing; the search scope is limited to the workspace, so never pass absolute paths outside it. Set `includeIgnored: true` only when the user explicitly asks to inspect ignored files or an ignored path is required for the task.");
13995
+ addToolRule(rules, toolNames, "Grep", "Use `Grep` to search file contents instead of shell text-search commands. Set `includeIgnored: true` only when the user explicitly asks to inspect ignored files or an ignored path is required for the task.");
13970
13996
  addToolRule(rules, toolNames, "Shell", "Use `Shell` for builds, tests, Git inspection, and commands without a dedicated tool. Keep commands scoped, non-interactive, and easy to audit.");
13971
13997
  addToolRule(rules, toolNames, "LspFindRefs", "Use `LspFindRefs` to find all references to a symbol using the Language Server Protocol. Prefer this over Grep when you need precise semantic results.");
13972
13998
  addToolRule(rules, toolNames, "LspHover", "Use `LspHover` to get type information and documentation for a symbol at a cursor position.");
@@ -22556,7 +22582,7 @@ ${expandSkillArguments(await skills.loadBody(skill), prompt)}`);
22556
22582
  ...additionalContext === void 0 ? {} : { additionalContext },
22557
22583
  ...getSteeringMessages === void 0 ? {} : { getSteeringMessages }
22558
22584
  })) {
22559
- if (event.type === "error" && /adapter|provider|api.?key|model/i.test(event.error.message)) {
22585
+ if (event.type === "error" && event.error.code !== "network" && event.error.code !== "rate_limit" && /adapter|provider|api.?key|model/i.test(event.error.message)) {
22560
22586
  yield { ...event, error: {
22561
22587
  ...event.error,
22562
22588
  message: `${event.error.message}. Configure providers and agents in .flavor/flavor.json or set OPENAI_API_KEY/ANTHROPIC_API_KEY.`
package/dist/cli.js CHANGED
@@ -3,7 +3,7 @@ import { createRequire } from "node:module"; const require = createRequire(impor
3
3
  import {
4
4
  FlavorRpcServer,
5
5
  TraceRecorder
6
- } from "./chunk-EJCI3VB5.js";
6
+ } from "./chunk-T2ARW6CZ.js";
7
7
  import {
8
8
  staticTaskLines
9
9
  } from "./chunk-KKIBYDJI.js";
@@ -23,7 +23,7 @@ import {
23
23
  packageVersion,
24
24
  redactErrorText,
25
25
  runPalBroker
26
- } from "./chunk-GAQJZBOF.js";
26
+ } from "./chunk-Y3DPUAEJ.js";
27
27
  import {
28
28
  McpServerConfigSchema,
29
29
  McpServerNameSchema,
@@ -877,7 +877,7 @@ async function runInteractiveCli(props) {
877
877
  const [{ render, AlternateScreen }, { createElement }, { App }] = await Promise.all([
878
878
  import("./claude-ink-ORUA7GWG.js"),
879
879
  import("react"),
880
- import("./app-OLOUQDIG.js")
880
+ import("./app-YSBW7GXH.js")
881
881
  ]);
882
882
  const instance = await render(createElement(
883
883
  AlternateScreen,
@@ -4256,6 +4256,8 @@ function normalizeProviderError(error) {
4256
4256
  code = "context_overflow";
4257
4257
  } else if (status === 404 || /model.*not.?found|not.?found.*model/.test(searchable)) {
4258
4258
  code = "model_not_found";
4259
+ } else if (status !== void 0 && status >= 500 && status <= 599) {
4260
+ code = "network";
4259
4261
  } else if (status === void 0 && /econn|enet|socket|network|fetch failed|connection|timeout/.test(searchable)) {
4260
4262
  code = "network";
4261
4263
  }
@@ -14603,8 +14605,8 @@ function toolsSection(toolNames) {
14603
14605
  addToolRule(rules, toolNames, "Write", "Use `Write` to create a file only when a new file is necessary.");
14604
14606
  addToolRule(rules, toolNames, "Edit", "Use `Edit` for precise replacements in existing files. Before editing, read the file and copy `oldText` verbatim from its actual current content \u2014 exact characters matter, including quote style (full-width vs ASCII) and version strings. Include enough surrounding lines to make the match unique.");
14605
14607
  addToolRule(rules, toolNames, "ApplyPatch", "Use `ApplyPatch` only when an edit genuinely spans multiple regions of one file; hunks may relocate only when their exact context has one unique nearby match. Prefer `Edit` for a single small replacement \u2014 it is easier to get right.");
14606
- addToolRule(rules, toolNames, "Glob", "Use `Glob` to find files by path pattern instead of shell directory crawling. Confirm the exact path before reading, searching, or editing; the search scope is limited to the workspace, so never pass absolute paths outside it.");
14607
- addToolRule(rules, toolNames, "Grep", "Use `Grep` to search file contents instead of shell text-search commands.");
14608
+ addToolRule(rules, toolNames, "Glob", "Use `Glob` to find files by path pattern instead of shell directory crawling. Confirm the exact path before reading, searching, or editing; the search scope is limited to the workspace, so never pass absolute paths outside it. Set `includeIgnored: true` only when the user explicitly asks to inspect ignored files or an ignored path is required for the task.");
14609
+ addToolRule(rules, toolNames, "Grep", "Use `Grep` to search file contents instead of shell text-search commands. Set `includeIgnored: true` only when the user explicitly asks to inspect ignored files or an ignored path is required for the task.");
14608
14610
  addToolRule(rules, toolNames, "Shell", "Use `Shell` for builds, tests, Git inspection, and commands without a dedicated tool. Keep commands scoped, non-interactive, and easy to audit.");
14609
14611
  addToolRule(rules, toolNames, "LspFindRefs", "Use `LspFindRefs` to find all references to a symbol using the Language Server Protocol. Prefer this over Grep when you need precise semantic results.");
14610
14612
  addToolRule(rules, toolNames, "LspHover", "Use `LspHover` to get type information and documentation for a symbol at a cursor position.");
@@ -17894,9 +17896,17 @@ var FILE_TYPE_EXTENSIONS = {
17894
17896
  python: [".py", ".pyi"],
17895
17897
  typescript: [".ts", ".tsx", ".mts", ".cts"]
17896
17898
  };
17899
+ var BooleanInput = z30.preprocess((value) => {
17900
+ if (typeof value !== "string") return value;
17901
+ const normalized = value.trim().toLowerCase();
17902
+ if (normalized === "true") return true;
17903
+ if (normalized === "false") return false;
17904
+ return value;
17905
+ }, z30.boolean());
17897
17906
  var GlobInput = z30.object({
17898
17907
  pattern: z30.string().min(1),
17899
17908
  path: z30.string().min(1).describe('Workspace-relative search directory. Use JSON null, not the string "null", for the workspace root.').nullable().optional(),
17909
+ includeIgnored: BooleanInput.describe("Include files excluded by .gitignore or .ignore. Git metadata remains excluded.").nullable().optional(),
17900
17910
  limit: z30.coerce.number().int().positive().max(1e5).nullable().optional()
17901
17911
  });
17902
17912
  var GrepInput = z30.object({
@@ -17904,6 +17914,7 @@ var GrepInput = z30.object({
17904
17914
  path: z30.string().min(1).describe('Workspace-relative search path. Use JSON null, not the string "null", for the workspace root.').nullable().optional(),
17905
17915
  glob: z30.string().min(1).nullable().optional(),
17906
17916
  fileType: z30.enum(FILE_TYPES).nullable().optional(),
17917
+ includeIgnored: BooleanInput.describe("Include files excluded by .gitignore or .ignore. Git metadata remains excluded.").nullable().optional(),
17907
17918
  context: z30.coerce.number().int().nonnegative().max(100).nullable().optional(),
17908
17919
  limit: z30.coerce.number().int().positive().max(1e5).nullable().optional()
17909
17920
  });
@@ -17917,23 +17928,26 @@ function createGlobTool(workspace, options = {}) {
17917
17928
  paths: (input) => [scope(root, searchPath(input.path))],
17918
17929
  summarize: (input) => {
17919
17930
  const path = searchPath(input.path);
17920
- return path ? `pattern: "${input.pattern}" in ${path}` : `pattern: "${input.pattern}"`;
17931
+ const ignored2 = input.includeIgnored === true ? " (including ignored files)" : "";
17932
+ return (path ? `pattern: "${input.pattern}" in ${path}` : `pattern: "${input.pattern}"`) + ignored2;
17921
17933
  },
17922
17934
  execute: async (input, signal) => {
17923
17935
  const limit = input.limit ?? options.defaultLimit ?? DEFAULT_RESULT_LIMIT;
17924
17936
  const start = scope(root, searchPath(input.path));
17937
+ if (isGitMetadataPath(root, start)) return { matches: [], truncated: false };
17925
17938
  const matcher = globRegex(input.pattern);
17926
17939
  const ignoreBudget = createIgnoreBudget(resources);
17940
+ const includeIgnored = input.includeIgnored === true;
17927
17941
  let paths;
17928
17942
  if (options.forceNode === true) {
17929
- paths = await nodeFiles(root, start, signal, (path) => matcher.test(path), limit + 1, resources, ignoreBudget);
17943
+ paths = await nodeFiles(root, start, signal, (path) => matcher.test(path), limit + 1, resources, ignoreBudget, includeIgnored);
17930
17944
  } else {
17931
17945
  try {
17932
- paths = await rgFiles(root, start, input.pattern, signal, options.rgPath ?? bundledRgPath, options.rgArgsPrefix ?? [], limit + 1, options.maxSearchBytes ?? DEFAULT_MAX_SEARCH_BYTES, resources, ignoreBudget);
17946
+ paths = await rgFiles(root, start, input.pattern, signal, options.rgPath ?? bundledRgPath, options.rgArgsPrefix ?? [], limit + 1, options.maxSearchBytes ?? DEFAULT_MAX_SEARCH_BYTES, resources, ignoreBudget, includeIgnored);
17933
17947
  } catch (error) {
17934
17948
  if (signal.aborted) throw signal.reason;
17935
17949
  if (!(error instanceof SearchSpawnError) || !error.fallbackSafe) throw error;
17936
- paths = await nodeFiles(root, start, signal, (path) => matcher.test(path), limit + 1, resources, createIgnoreBudget(resources));
17950
+ paths = await nodeFiles(root, start, signal, (path) => matcher.test(path), limit + 1, resources, createIgnoreBudget(resources), includeIgnored);
17937
17951
  }
17938
17952
  }
17939
17953
  const matches = paths.filter((path) => matcher.test(path)).sort(comparePaths);
@@ -17953,24 +17967,27 @@ function createGrepTool(workspace, options = {}) {
17953
17967
  const path = searchPath(input.path);
17954
17968
  const where = path ? ` in ${path}` : "";
17955
17969
  const kind = input.fileType ? ` [${input.fileType}]` : "";
17956
- return `pattern: /${input.pattern}/${kind}${where}`;
17970
+ const ignored2 = input.includeIgnored === true ? " (including ignored files)" : "";
17971
+ return `pattern: /${input.pattern}/${kind}${where}${ignored2}`;
17957
17972
  },
17958
17973
  execute: async (input, signal) => {
17959
17974
  const expression = new RegExp(input.pattern);
17960
17975
  const limit = input.limit ?? options.defaultLimit ?? DEFAULT_RESULT_LIMIT;
17961
17976
  const context = input.context ?? 0;
17962
17977
  const start = await resolveGrepPath(root, searchPath(input.path));
17978
+ if (isGitMetadataPath(root, start)) return { matches: [], truncated: false };
17963
17979
  const ignoreBudget = createIgnoreBudget(resources);
17980
+ const includeIgnored = input.includeIgnored === true;
17964
17981
  let matches;
17965
17982
  if (options.forceNode === true) {
17966
- matches = await nodeGrep(root, start, input.glob ?? void 0, input.fileType ?? void 0, expression, context, signal, limit + 1, options.maxFileBytes ?? DEFAULT_MAX_FILE_BYTES, options.maxSearchBytes ?? DEFAULT_MAX_SEARCH_BYTES, resources, ignoreBudget);
17983
+ matches = await nodeGrep(root, start, input.glob ?? void 0, input.fileType ?? void 0, expression, context, signal, limit + 1, options.maxFileBytes ?? DEFAULT_MAX_FILE_BYTES, options.maxSearchBytes ?? DEFAULT_MAX_SEARCH_BYTES, resources, ignoreBudget, includeIgnored);
17967
17984
  } else {
17968
17985
  try {
17969
17986
  matches = await rgGrep(root, start, input, context, signal, options.rgPath ?? bundledRgPath, options.rgArgsPrefix ?? [], limit + 1, options.maxFileBytes ?? DEFAULT_MAX_FILE_BYTES, options.maxSearchBytes ?? DEFAULT_MAX_SEARCH_BYTES, resources, ignoreBudget);
17970
17987
  } catch (error) {
17971
17988
  if (signal.aborted) throw signal.reason;
17972
17989
  if (!(error instanceof SearchSpawnError) || !error.fallbackSafe) throw error;
17973
- matches = await nodeGrep(root, start, input.glob ?? void 0, input.fileType ?? void 0, expression, context, signal, limit + 1, options.maxFileBytes ?? DEFAULT_MAX_FILE_BYTES, options.maxSearchBytes ?? DEFAULT_MAX_SEARCH_BYTES, resources, createIgnoreBudget(resources));
17990
+ matches = await nodeGrep(root, start, input.glob ?? void 0, input.fileType ?? void 0, expression, context, signal, limit + 1, options.maxFileBytes ?? DEFAULT_MAX_FILE_BYTES, options.maxSearchBytes ?? DEFAULT_MAX_SEARCH_BYTES, resources, createIgnoreBudget(resources), includeIgnored);
17974
17991
  }
17975
17992
  }
17976
17993
  matches.sort(compareGrepMatches);
@@ -17978,10 +17995,10 @@ function createGrepTool(workspace, options = {}) {
17978
17995
  }
17979
17996
  };
17980
17997
  }
17981
- async function rgFiles(root, start, pattern, signal, executable, argsPrefix, limit, maxBytes, resources, ignoreBudget) {
17998
+ async function rgFiles(root, start, pattern, signal, executable, argsPrefix, limit, maxBytes, resources, ignoreBudget, includeIgnored) {
17982
17999
  const target = relative17(root, start) || ".";
17983
18000
  const matcher = globRegex(pattern);
17984
- const ignoreLayers = await collectIgnoreLayers(root, start, signal, resources, ignoreBudget);
18001
+ const ignoreLayers = includeIgnored ? [] : await collectIgnoreLayers(root, start, signal, resources, ignoreBudget);
17985
18002
  const paths = [];
17986
18003
  const parser = delimitedParser(0, (record3) => {
17987
18004
  if (record3.length === 0) return true;
@@ -17990,7 +18007,10 @@ async function rgFiles(root, start, pattern, signal, executable, argsPrefix, lim
17990
18007
  retainTopK(paths, path, limit, comparePaths);
17991
18008
  return true;
17992
18009
  });
17993
- const output = await runStreaming(executable, [...argsPrefix, "--files", "--null", "--sort", "path", "--hidden", "--glob", "!.git", "--glob", pattern, "--", target], root, signal, maxBytes, parser);
18010
+ const args = [...argsPrefix, "--files", "--null", "--sort", "path", "--hidden", "--glob", "!.git", "--glob", "!.git/**"];
18011
+ if (includeIgnored) args.push("--no-ignore");
18012
+ args.push("--glob", pattern, "--", target);
18013
+ const output = await runStreaming(executable, args, root, signal, maxBytes, parser);
17994
18014
  if (!output.stoppedEarly && output.code !== 0 && output.code !== 1) throw new Error(output.stderr || `ripgrep exited with ${output.code}`);
17995
18015
  parser.finish();
17996
18016
  return paths;
@@ -18000,12 +18020,13 @@ async function rgGrep(root, start, input, context, signal, executable, argsPrefi
18000
18020
  if (input.fileType !== void 0 && input.fileType !== null && typeExtensions === void 0) {
18001
18021
  throw new Error(`Unsupported file type: ${input.fileType}`);
18002
18022
  }
18003
- const args = ["--json", "--line-number", "--column", "--sort", "path", "--hidden", "--glob", "!.git", "--max-filesize", String(maxFileBytes), "--context", String(context)];
18023
+ const args = ["--json", "--line-number", "--column", "--sort", "path", "--hidden", "--glob", "!.git", "--glob", "!.git/**", "--max-filesize", String(maxFileBytes), "--context", String(context)];
18024
+ if (input.includeIgnored === true) args.push("--no-ignore");
18004
18025
  if (input.glob !== void 0 && input.glob !== null) args.push("--glob", input.glob);
18005
18026
  else for (const extension2 of typeExtensions ?? []) args.push("--glob", `*${extension2}`);
18006
18027
  args.push("--regexp", input.pattern, "--", relative17(root, start) || ".");
18007
18028
  const matches = [];
18008
- const ignoreLayers = await collectIgnoreLayers(root, start, signal, resources, ignoreBudget);
18029
+ const ignoreLayers = input.includeIgnored === true ? [] : await collectIgnoreLayers(root, start, signal, resources, ignoreBudget);
18009
18030
  const parser = delimitedParser(10, (record3) => {
18010
18031
  if (record3.length === 0) return true;
18011
18032
  const event = JSON.parse(decodeUtf82(record3, "ripgrep JSON"));
@@ -18060,8 +18081,8 @@ async function hydrateContext(root, matches, context, signal, maxFileBytes, maxT
18060
18081
  }
18061
18082
  }
18062
18083
  }
18063
- async function nodeGrep(root, start, glob, type, expression, context, signal, maxMatches, maxFileBytes, maxSearchBytes, resources, ignoreBudget) {
18064
- const files = await nodeFiles(root, start, signal, () => true, resources.maxDiscoveredFiles + 1, resources, ignoreBudget);
18084
+ async function nodeGrep(root, start, glob, type, expression, context, signal, maxMatches, maxFileBytes, maxSearchBytes, resources, ignoreBudget, includeIgnored) {
18085
+ const files = await nodeFiles(root, start, signal, () => true, resources.maxDiscoveredFiles + 1, resources, ignoreBudget, includeIgnored);
18065
18086
  if (files.length > resources.maxDiscoveredFiles) throw new Error(`Aggregate discovered file limit of ${resources.maxDiscoveredFiles} exceeded`);
18066
18087
  const matcher = glob === void 0 ? void 0 : globRegex(glob);
18067
18088
  const extension2 = type === void 0 ? void 0 : typeExtension(type);
@@ -18103,23 +18124,25 @@ async function nodeGrep(root, start, glob, type, expression, context, signal, ma
18103
18124
  }
18104
18125
  return matches;
18105
18126
  }
18106
- async function nodeFiles(root, start, signal, accept, limit, resources, ignoreBudget) {
18127
+ async function nodeFiles(root, start, signal, accept, limit, resources, ignoreBudget, includeIgnored) {
18107
18128
  const ignores = [];
18108
18129
  const output = [];
18109
18130
  const delta = relative17(root, start);
18110
18131
  const segments = delta === "" ? [] : delta.split(sep17);
18111
18132
  let ancestor = root;
18112
- for (let index = 0; index < segments.length; index += 1) {
18113
- noteIgnoreDirectory(ignoreBudget);
18114
- await loadIgnoreFiles(ancestor, normalizedRelative(root, ancestor), ignores, ignoreBudget, signal);
18115
- ancestor = resolve24(ancestor, segments[index]);
18133
+ if (!includeIgnored) {
18134
+ for (let index = 0; index < segments.length; index += 1) {
18135
+ noteIgnoreDirectory(ignoreBudget);
18136
+ await loadIgnoreFiles(ancestor, normalizedRelative(root, ancestor), ignores, ignoreBudget, signal);
18137
+ ancestor = resolve24(ancestor, segments[index]);
18138
+ }
18116
18139
  }
18117
18140
  async function walk(directory) {
18118
18141
  abort(signal);
18119
18142
  const relativeDirectory = normalizedRelative(root, directory);
18120
18143
  const ruleCount = ignores.length;
18121
18144
  noteIgnoreDirectory(ignoreBudget);
18122
- await loadIgnoreFiles(directory, relativeDirectory, ignores, ignoreBudget, signal);
18145
+ if (!includeIgnored) await loadIgnoreFiles(directory, relativeDirectory, ignores, ignoreBudget, signal);
18123
18146
  const handle = await opendir(directory);
18124
18147
  const entries = [];
18125
18148
  for await (const entry2 of handle) {
@@ -18132,7 +18155,7 @@ async function nodeFiles(root, start, signal, accept, limit, resources, ignoreBu
18132
18155
  abort(signal);
18133
18156
  const absolute = resolve24(directory, entry2.name);
18134
18157
  const path = normalizedRelative(root, absolute);
18135
- if (entry2.name === ".git" || ignored(path, entry2.isDirectory(), ignores)) continue;
18158
+ if (entry2.name === ".git" || !includeIgnored && ignored(path, entry2.isDirectory(), ignores)) continue;
18136
18159
  if (entry2.isDirectory()) await walk(absolute);
18137
18160
  else if (entry2.isFile() && accept(path)) output.push(path);
18138
18161
  if (output.length >= limit) break;
@@ -18301,6 +18324,9 @@ function normalizedRelative(root, path) {
18301
18324
  function normalizePath(path) {
18302
18325
  return path.replaceAll("\\", "/");
18303
18326
  }
18327
+ function isGitMetadataPath(root, path) {
18328
+ return normalizedRelative(root, path).split("/").some((segment) => segment.toLowerCase() === ".git");
18329
+ }
18304
18330
  function comparePaths(a, b) {
18305
18331
  return a < b ? -1 : a > b ? 1 : 0;
18306
18332
  }
@@ -26341,7 +26367,7 @@ ${expandSkillArguments(await skills.loadBody(skill), prompt)}`);
26341
26367
  ...additionalContext === void 0 ? {} : { additionalContext },
26342
26368
  ...getSteeringMessages === void 0 ? {} : { getSteeringMessages }
26343
26369
  })) {
26344
- if (event.type === "error" && /adapter|provider|api.?key|model/i.test(event.error.message)) {
26370
+ if (event.type === "error" && event.error.code !== "network" && event.error.code !== "rate_limit" && /adapter|provider|api.?key|model/i.test(event.error.message)) {
26345
26371
  yield { ...event, error: {
26346
26372
  ...event.error,
26347
26373
  message: `${event.error.message}. Configure providers and agents in .flavor/flavor.json or set OPENAI_API_KEY/ANTHROPIC_API_KEY.`
package/dist/sdk/index.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  FlavorRpcServer,
5
5
  TraceRecordSchema,
6
6
  TraceRecorder
7
- } from "../chunk-EJCI3VB5.js";
7
+ } from "../chunk-T2ARW6CZ.js";
8
8
  import {
9
9
  AgentMessageQueue,
10
10
  DockerExecutionEnvironment,
@@ -13,7 +13,7 @@ import {
13
13
  WorkspaceCheckpointStore,
14
14
  buildDockerInvocation,
15
15
  createProductionRuntime
16
- } from "../chunk-GAQJZBOF.js";
16
+ } from "../chunk-Y3DPUAEJ.js";
17
17
  import "../chunk-IG4Z23CL.js";
18
18
  import "../chunk-RQTYHUMK.js";
19
19
  import "../chunk-S32JRDZK.js";
@@ -3,6 +3,7 @@ import type { ToolDefinition } from "./types.js";
3
3
  declare const GlobInput: z.ZodObject<{
4
4
  pattern: z.ZodString;
5
5
  path: z.ZodOptional<z.ZodNullable<z.ZodString>>;
6
+ includeIgnored: z.ZodOptional<z.ZodNullable<z.ZodPreprocess<z.ZodBoolean>>>;
6
7
  limit: z.ZodOptional<z.ZodNullable<z.ZodCoercedNumber<unknown>>>;
7
8
  }, z.core.$strip>;
8
9
  declare const GrepInput: z.ZodObject<{
@@ -40,6 +41,7 @@ declare const GrepInput: z.ZodObject<{
40
41
  xml: "xml";
41
42
  yaml: "yaml";
42
43
  }>>>;
44
+ includeIgnored: z.ZodOptional<z.ZodNullable<z.ZodPreprocess<z.ZodBoolean>>>;
43
45
  context: z.ZodOptional<z.ZodNullable<z.ZodCoercedNumber<unknown>>>;
44
46
  limit: z.ZodOptional<z.ZodNullable<z.ZodCoercedNumber<unknown>>>;
45
47
  }, z.core.$strip>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flavor-code",
3
- "version": "1.3.8",
3
+ "version": "1.3.10",
4
4
  "author": "YachuanWzh",
5
5
  "type": "module",
6
6
  "publishConfig": {