@allansantos-dev/smart-tool 0.0.0-stage → 0.9.0

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 (77) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/LICENSE +202 -0
  3. package/NOTICE +32 -0
  4. package/README.md +116 -3
  5. package/atomic_io.py +94 -0
  6. package/autostart.py +199 -0
  7. package/bin/smart-tool.mjs +82 -0
  8. package/browser_service_client.py +232 -0
  9. package/capabilities.py +63 -0
  10. package/client_hooks.py +192 -0
  11. package/code_graph.py +403 -0
  12. package/code_graph_java.mjs +49 -0
  13. package/code_graph_js.cjs +135 -0
  14. package/config.py +241 -0
  15. package/daemon_launcher.py +165 -0
  16. package/directory_watch.py +131 -0
  17. package/document_text.py +69 -0
  18. package/duplicates.py +313 -0
  19. package/embedding_cache.py +99 -0
  20. package/endpoint_sync.py +179 -0
  21. package/folder_picker.py +73 -0
  22. package/freshness.py +278 -0
  23. package/gateway.py +220 -0
  24. package/hook_decision.py +96 -0
  25. package/hooks/pretool_router.py +45 -0
  26. package/index_inventory.py +75 -0
  27. package/index_profile.py +167 -0
  28. package/index_scope.py +458 -0
  29. package/index_views.py +121 -0
  30. package/indexer.py +878 -0
  31. package/install.py +251 -0
  32. package/install_runtime.py +249 -0
  33. package/integration_metrics.py +82 -0
  34. package/local_embedder.py +172 -0
  35. package/model_adapters/__init__.py +0 -0
  36. package/model_adapters/openai_compatible.py +57 -0
  37. package/model_catalog.py +74 -0
  38. package/model_client.py +38 -0
  39. package/model_defaults.py +70 -0
  40. package/package.json +35 -6
  41. package/paths.py +6 -0
  42. package/project_identity.py +42 -0
  43. package/project_insights_ui.py +38 -0
  44. package/project_maps_ui.py +96 -0
  45. package/project_monitor.py +204 -0
  46. package/project_scheduler.py +61 -0
  47. package/project_storage.py +165 -0
  48. package/project_store.py +220 -0
  49. package/projects_ui.py +146 -0
  50. package/requirements.txt +8 -0
  51. package/research_cache.py +171 -0
  52. package/research_metrics.py +110 -0
  53. package/router.py +582 -0
  54. package/secret_store.py +121 -0
  55. package/setup_ui.py +986 -0
  56. package/site_memory.py +53 -0
  57. package/smart_tool_daemon.py +3604 -0
  58. package/tray.py +245 -0
  59. package/update_check.py +22 -0
  60. package/usage_meter.py +124 -0
  61. package/version.py +18 -0
  62. package/view_compare.py +68 -0
  63. package/web_adapters/browser/browser_service.py +302 -0
  64. package/web_adapters/browser/crawl4ai_search.py +236 -0
  65. package/web_adapters/browser/requirements.txt +2 -0
  66. package/web_adapters/node/adapter-common.mjs +40 -0
  67. package/web_adapters/node/ddg-search.mjs +89 -0
  68. package/web_adapters/node/open-websearch-adapter.mjs +77 -0
  69. package/web_adapters/node/package-lock.json +2720 -0
  70. package/web_adapters/node/package.json +12 -0
  71. package/web_adapters/node/wikipedia-search.mjs +44 -0
  72. package/web_document_graph.py +71 -0
  73. package/web_fetch.py +242 -0
  74. package/web_search_adapters.py +193 -0
  75. package/web_search_ddgs.py +42 -0
  76. package/web_search_external.py +288 -0
  77. package/web_search_health.py +88 -0
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env node
2
+ // Uso: node open-websearch-adapter.mjs "consulta" [--num 8] [--engine duckduckgo]
3
+ // Saída: JSON no stdout — [{ title, url, snippet }, ...]
4
+ // Wrapper fino sobre o pacote npm `open-websearch` (scraping multi-engine, sem chave de
5
+ // API) para expor o mesmo contrato dos demais adaptadores de web_search do Smart Tool
6
+ // (ver web_search_adapters.py no smart-tool) — o CLI do pacote devolve um envelope
7
+ // {data:{results:[...],partialFailures:[...]}} com campo `description`, não o array
8
+ // {title,url,snippet} que este contrato exige.
9
+ import { execFileSync } from 'node:child_process';
10
+ import { existsSync } from 'node:fs';
11
+ import path from 'node:path';
12
+ import { fileURLToPath } from 'node:url';
13
+
14
+ import { parseArgs } from './adapter-common.mjs';
15
+
16
+ // `npm root -g`/`npx` são `.cmd` no Windows -- `execFileSync` sem shell não invoca (EINVAL),
17
+ // e com shell:true o Node concatena argumentos sem escapar (DEP0190). O pacote fica
18
+ // instalado ao lado deste script por `install_runtime.py`; a chamada usa o arquivo JS
19
+ // diretamente com `process.execPath`. `OPEN_WEBSEARCH_CLI` permite diagnóstico local.
20
+ const LOCAL_DIR = path.dirname(fileURLToPath(import.meta.url));
21
+ const OPEN_WEBSEARCH_CLI = process.env.OPEN_WEBSEARCH_CLI || path.join(
22
+ LOCAL_DIR, 'node_modules', 'open-websearch', 'build', 'index.js',
23
+ );
24
+
25
+ function main() {
26
+ const { query, num, engine } = parseArgs(process.argv.slice(2),
27
+ 'Usage: node open-websearch-adapter.mjs "query" [--num 8] [--engine name]', { num: 8, engine: 'duckduckgo' });
28
+
29
+ if (!existsSync(OPEN_WEBSEARCH_CLI)) {
30
+ throw new Error(`open-websearch is not installed (${OPEN_WEBSEARCH_CLI} does not exist); run: python install_runtime.py`);
31
+ }
32
+
33
+ // O banner de log do pacote vai pro stderr (confirmado ao vivo); stdout fica só com o
34
+ // JSON do `--json`, então captar só stdout aqui não mistura texto solto com o parse.
35
+ let raw;
36
+ try {
37
+ raw = execFileSync(
38
+ process.execPath,
39
+ [OPEN_WEBSEARCH_CLI, 'search', query, '--engine', engine, '--limit', String(num), '--json'],
40
+ { encoding: 'utf-8', timeout: 25000 },
41
+ );
42
+ } catch (err) {
43
+ const detail = (err.stderr || '').toString().trim();
44
+ throw new Error(detail || String(err.message || err));
45
+ }
46
+
47
+ const envelope = JSON.parse(raw);
48
+ if (envelope.error) {
49
+ throw new Error(String(envelope.error));
50
+ }
51
+
52
+ const results = (envelope.data?.results ?? []).slice(0, num).map((r) => ({
53
+ title: r.title ?? '',
54
+ url: r.url ?? '',
55
+ snippet: r.description ?? '',
56
+ }));
57
+
58
+ if (results.length === 0) {
59
+ const failures = envelope.data?.partialFailures ?? [];
60
+ const reason = failures.length
61
+ ? failures.map((f) => `${f.engine}: ${f.message}`).join('; ')
62
+ : 'no results';
63
+ throw new Error(`No result extracted (${engine}): ${reason}`);
64
+ }
65
+
66
+ process.stdout.write(JSON.stringify(results));
67
+ }
68
+
69
+ // Nunca process.exit() aqui: execFileSync já é síncrono (sem handle assíncrono pendente
70
+ // no momento do catch), mas o padrão do projeto (ver ddg-search.mjs) é sempre
71
+ // process.exitCode em vez de exit() com stdout/stderr em pipe.
72
+ try {
73
+ main();
74
+ } catch (err) {
75
+ console.error(String(err?.message ?? err));
76
+ process.exitCode = 1;
77
+ }