recker 1.0.12-alpha.91ed191 → 1.0.12-next.b76976a

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.
@@ -11,6 +11,7 @@ import { getSecurityRecords } from '../../utils/dns-toolkit.js';
11
11
  import { rdap } from '../../utils/rdap.js';
12
12
  import { ScrapeDocument } from '../../scrape/document.js';
13
13
  import colors from '../../utils/colors.js';
14
+ import { getShellSearch } from './shell-search.js';
14
15
  let highlight;
15
16
  async function initDependencies() {
16
17
  if (!highlight) {
@@ -86,6 +87,7 @@ export class RekShell {
86
87
  'ws', 'udp', 'load', 'chat', 'ai',
87
88
  'whois', 'tls', 'ssl', 'dns', 'rdap', 'ping',
88
89
  'scrap', '$', '$text', '$attr', '$html', '$links', '$images', '$scripts', '$css', '$sourcemaps', '$unmap', '$unmap:view', '$unmap:save', '$beautify', '$beautify:save', '$table',
90
+ '?', 'search', 'suggest', 'example',
89
91
  'help', 'clear', 'exit', 'set', 'url', 'vars', 'env'
90
92
  ];
91
93
  const hits = commands.filter((c) => c.startsWith(line));
@@ -217,6 +219,23 @@ export class RekShell {
217
219
  case '$table':
218
220
  await this.runSelectTable(parts.slice(1).join(' '));
219
221
  return;
222
+ case '?':
223
+ case 'search':
224
+ await this.runSearch(parts.slice(1).join(' '));
225
+ return;
226
+ case 'suggest':
227
+ await this.runSuggest(parts.slice(1).join(' '));
228
+ return;
229
+ case 'example':
230
+ await this.runExample(parts.slice(1).join(' '));
231
+ return;
232
+ }
233
+ if (input.endsWith('?') && !input.startsWith('http')) {
234
+ const query = input.slice(0, -1).trim();
235
+ if (query) {
236
+ await this.runSearch(query);
237
+ return;
238
+ }
220
239
  }
221
240
  const methods = ['get', 'post', 'put', 'delete', 'patch', 'head', 'options'];
222
241
  let method = 'GET';
@@ -1640,6 +1659,117 @@ export class RekShell {
1640
1659
  }
1641
1660
  console.log('');
1642
1661
  }
1662
+ async runSearch(query) {
1663
+ if (!query.trim()) {
1664
+ console.log(colors.yellow('Usage: ? <query> or search <query>'));
1665
+ console.log(colors.gray(' Examples:'));
1666
+ console.log(colors.gray(' ? retry exponential backoff'));
1667
+ console.log(colors.gray(' search cache configuration'));
1668
+ return;
1669
+ }
1670
+ console.log(colors.gray('Searching documentation...'));
1671
+ try {
1672
+ const search = getShellSearch();
1673
+ const results = await search.search(query, { limit: 5 });
1674
+ if (results.length === 0) {
1675
+ console.log(colors.yellow(`No results for: "${query}"`));
1676
+ console.log(colors.gray('Try different keywords like: retry, cache, streaming, websocket, pagination'));
1677
+ return;
1678
+ }
1679
+ console.log(colors.bold(colors.cyan(`\nFound ${results.length} results for "${query}":\n`)));
1680
+ for (let i = 0; i < results.length; i++) {
1681
+ const result = results[i];
1682
+ const score = Math.round(result.score * 100);
1683
+ console.log(` ${colors.green(`${i + 1}.`)} ${colors.bold(result.title)} ${colors.gray(`(${score}%)`)}`);
1684
+ console.log(` ${colors.gray(result.path)}`);
1685
+ if (result.snippet) {
1686
+ const snippet = result.snippet.slice(0, 120).replace(/\n/g, ' ');
1687
+ console.log(` ${colors.gray(snippet)}${result.snippet.length > 120 ? '...' : ''}`);
1688
+ }
1689
+ console.log('');
1690
+ }
1691
+ console.log(colors.gray(' Tip: Use "get_doc <path>" to read full documentation'));
1692
+ }
1693
+ catch (error) {
1694
+ console.error(colors.red(`Search failed: ${error.message}`));
1695
+ }
1696
+ }
1697
+ async runSuggest(useCase) {
1698
+ if (!useCase.trim()) {
1699
+ console.log(colors.yellow('Usage: suggest <use-case>'));
1700
+ console.log(colors.gray(' Examples:'));
1701
+ console.log(colors.gray(' suggest implement retry with exponential backoff'));
1702
+ console.log(colors.gray(' suggest cache API responses'));
1703
+ console.log(colors.gray(' suggest stream AI responses from OpenAI'));
1704
+ return;
1705
+ }
1706
+ console.log(colors.gray('Getting suggestions...'));
1707
+ try {
1708
+ const search = getShellSearch();
1709
+ const suggestion = await search.suggest(useCase);
1710
+ console.log('');
1711
+ this.printMarkdown(suggestion);
1712
+ }
1713
+ catch (error) {
1714
+ console.error(colors.red(`Suggest failed: ${error.message}`));
1715
+ }
1716
+ }
1717
+ async runExample(feature) {
1718
+ if (!feature.trim()) {
1719
+ console.log(colors.yellow('Usage: example <feature>'));
1720
+ console.log(colors.gray(' Examples:'));
1721
+ console.log(colors.gray(' example retry'));
1722
+ console.log(colors.gray(' example streaming'));
1723
+ console.log(colors.gray(' example cache'));
1724
+ console.log(colors.gray(' example websocket'));
1725
+ return;
1726
+ }
1727
+ console.log(colors.gray('Finding examples...'));
1728
+ try {
1729
+ const search = getShellSearch();
1730
+ const examples = await search.getExamples(feature, { limit: 3 });
1731
+ console.log('');
1732
+ this.printMarkdown(examples);
1733
+ }
1734
+ catch (error) {
1735
+ console.error(colors.red(`Example lookup failed: ${error.message}`));
1736
+ }
1737
+ }
1738
+ printMarkdown(text) {
1739
+ const lines = text.split('\n');
1740
+ for (const line of lines) {
1741
+ if (line.startsWith('**') && line.endsWith('**')) {
1742
+ console.log(colors.bold(line.replace(/\*\*/g, '')));
1743
+ }
1744
+ else if (line.startsWith('### ')) {
1745
+ console.log(colors.bold(colors.cyan(line.slice(4))));
1746
+ }
1747
+ else if (line.startsWith('## ')) {
1748
+ console.log(colors.bold(colors.cyan(line.slice(3))));
1749
+ }
1750
+ else if (line.startsWith('# ')) {
1751
+ console.log(colors.bold(colors.cyan(line.slice(2))));
1752
+ }
1753
+ else if (line.startsWith('```')) {
1754
+ if (line.length > 3) {
1755
+ console.log(colors.gray('─'.repeat(40)));
1756
+ }
1757
+ else {
1758
+ console.log(colors.gray('─'.repeat(40)));
1759
+ }
1760
+ }
1761
+ else if (line.startsWith(' - ') || line.startsWith('- ')) {
1762
+ const content = line.replace(/^\s*-\s*/, '');
1763
+ console.log(` ${colors.green('•')} ${content}`);
1764
+ }
1765
+ else if (line.match(/^\s+/)) {
1766
+ console.log(colors.yellow(line));
1767
+ }
1768
+ else {
1769
+ console.log(line);
1770
+ }
1771
+ }
1772
+ }
1643
1773
  printHelp() {
1644
1774
  console.log(`
1645
1775
  ${colors.bold(colors.cyan('Rek Console Help'))}
@@ -1698,6 +1828,12 @@ export class RekShell {
1698
1828
  ${colors.green('$beautify:save [f]')} Save beautified code to file.
1699
1829
  ${colors.green('$table <selector>')} Extract table as data.
1700
1830
 
1831
+ ${colors.bold('Documentation:')}
1832
+ ${colors.green('? <query>')} Search Recker documentation.
1833
+ ${colors.green('search <query>')} Alias for ? (hybrid fuzzy+semantic search).
1834
+ ${colors.green('suggest <use-case>')} Get implementation suggestions.
1835
+ ${colors.green('example <feature>')} Get code examples for a feature.
1836
+
1701
1837
  ${colors.bold('Examples:')}
1702
1838
  › url httpbin.org
1703
1839
  › get /json