@molecule/api-ai-tools 1.6.5 → 1.6.6

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/utilities.js CHANGED
@@ -684,9 +684,104 @@ export function isValidGlob(pattern) {
684
684
  export function findPatternArgs(pattern) {
685
685
  if (!pattern.includes('/'))
686
686
  return `-name ${shellQuote(pattern)}`;
687
+ return findPathArgs(pattern);
688
+ }
689
+ /**
690
+ * The `-path` alternatives of {@link findPatternArgs}, for a pattern whose
691
+ * directory the caller has already rooted the search at.
692
+ *
693
+ * `find_files` narrows the search root itself when the pattern spells its own
694
+ * directory out (see {@link literalDirPrefix}) — `node_modules` plus
695
+ * `@molecule/api-resource-user/dist/*.d.ts` searched that one directory. The
696
+ * remainder (`*.d.ts`) must then keep the `-path` form rather than collapsing to
697
+ * `-name`: `*` crosses `/` in an fnmatch glob, so the `-path` form still finds a
698
+ * declaration file in a `dist/utilities/` subdirectory, which `-name '*.d.ts'`
699
+ * would drop (a silent partial answer, which is worse than the timeout it
700
+ * replaced).
701
+ *
702
+ * @param pattern - The pattern's remainder, with a `/` in it or not.
703
+ * @returns One or more `-path '…'` alternatives, ORed inside parens when there
704
+ * is more than one.
705
+ */
706
+ export function findPathArgs(pattern) {
687
707
  const paths = pathPatternVariants(pattern).map((p) => `-path ${shellQuote(`*/${p}`)}`);
688
708
  return paths.length === 1 ? paths[0] : `\\( ${paths.join(' -o ')} \\)`;
689
709
  }
710
+ /**
711
+ * The directory a GLOB pattern spells out, when it spells one out: everything
712
+ * before the pattern's first glob character, trimmed back to the last `/`.
713
+ *
714
+ * A pattern is matched against the whole path with a leading "any parent"
715
+ * anchor ({@link findPatternArgs}), so `find` visits every entry below the
716
+ * search root. Handed `/workspace/node_modules` and
717
+ * `@molecule/api-resource-user/dist/*.d.ts` — a directory named outright —
718
+ * `find` walked the sandbox's entire dependency tree and hit the tool's 10 s
719
+ * deadline without printing a result (xr-molecule-flash-m94: the one directory
720
+ * the model meant answered a `list_files` in 0 s). The literal prefix is that
721
+ * directory, and rooting the search at it is what keeps the call instant.
722
+ *
723
+ * A BARE first segment (`helpers/*`, `bonds/*`, `e2e/*.spec.ts`) is NOT one:
724
+ * `helpers/*` means "a `helpers/` directory anywhere below the root", which the
725
+ * tool documents and a live run relied on (xr-molecule-flash-m77 — a path
726
+ * pattern is not anchored to one depth). Rooting those at
727
+ * `<root>/helpers` would answer with a SUBSET, silently: the nested
728
+ * `api/src/helpers/` matches would disappear, and a missing file reads as
729
+ * "no such file". So a prefix is returned only when it names a path of two or
730
+ * more segments (`@molecule/api-resource-user/dist`), which is the shape that
731
+ * is a directory rather than a directory name.
732
+ *
733
+ * @param pattern - A pattern already accepted by {@link isValidGlob}.
734
+ * @returns The literal directory prefix, without a trailing slash, or null when
735
+ * the pattern has no glob character, no `/`, or only a bare name before one.
736
+ */
737
+ export function literalDirPrefix(pattern) {
738
+ const stripped = pattern.replace(/^(?:\.?\/)+/, '');
739
+ const firstGlob = stripped.search(/[?*[]/);
740
+ // No glob at all: the pattern IS a path, and the whole-tree form already
741
+ // finds it at any depth.
742
+ if (firstGlob === -1)
743
+ return null;
744
+ const at = stripped.slice(0, firstGlob).lastIndexOf('/');
745
+ if (at <= 0)
746
+ return null;
747
+ const prefix = stripped.slice(0, at);
748
+ return prefix.includes('/') ? prefix : null;
749
+ }
750
+ /**
751
+ * Whether a backend error is the sandbox's own command deadline.
752
+ *
753
+ * The E2B SDK answers a timed-out `exec` with its generic text —
754
+ * `[deadline_exceeded] the operation timed out: … It can be modified by passing
755
+ * 'timeoutMs' when making the request. Use '0' to disable the timeout.` — which
756
+ * names an option the executor cannot set and says nothing about the search
757
+ * that died. Handing that sentence to the model is what xr-molecule-flash-m94
758
+ * read after `find_files` spent 10 s walking `node_modules`; the tool answers
759
+ * the deadline in its own words instead (see {@link searchTimeoutError}).
760
+ *
761
+ * @param error - The error the backend threw.
762
+ * @returns True when the error reads as a timeout or a deadline.
763
+ */
764
+ export function isCommandTimeout(error) {
765
+ const message = error instanceof Error ? error.message : String(error);
766
+ return /deadline[_ ]?exceeded|timed out|timeout/i.test(message);
767
+ }
768
+ /**
769
+ * The answer a search tool gives when the backend's deadline fires: what was
770
+ * searched, for what, how long the tool allowed, and the two ways to get an
771
+ * answer — a narrower `path`, or a listing. Never the vendor's `timeoutMs`
772
+ * sentence (see {@link isCommandTimeout}).
773
+ *
774
+ * @param tool - The tool that timed out (`find_files`, `search_files`).
775
+ * @param searched - The directory the search actually covered.
776
+ * @param pattern - The pattern it was searching for.
777
+ * @param seconds - The tool's own limit, in seconds.
778
+ * @param hint - What to do differently — the narrower target or the listing tool.
779
+ * @returns The message's text.
780
+ */
781
+ export function searchTimeoutError(tool, searched, pattern, seconds, hint) {
782
+ return (`${tool} timed out after ${seconds}s searching ${searched} for "${pattern}" — the sandbox stopped the ` +
783
+ `command at its deadline, so there is no result (this is not an empty directory). ${hint}`);
784
+ }
690
785
  /**
691
786
  * The `-path` globs for a pattern that contains a slash, one per way each
692
787
  * doubled-star directory segment can stand for zero directories.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@molecule/api-ai-tools",
3
- "version": "1.6.5",
3
+ "version": "1.6.6",
4
4
  "description": "Shared AI agent tools with backend abstraction for sandbox and local execution",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",