@allansantos-dev/smart-tool 0.9.0 → 0.9.2

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 (41) hide show
  1. package/CHANGELOG.md +50 -23
  2. package/NOTICE +32 -32
  3. package/README.md +117 -116
  4. package/atomic_io.py +94 -94
  5. package/bin/smart-tool.mjs +5 -1
  6. package/client_hooks.py +192 -192
  7. package/code_graph_java.mjs +49 -49
  8. package/code_graph_js.cjs +135 -135
  9. package/duplicates.py +313 -313
  10. package/embedding_cache.py +99 -99
  11. package/endpoint_sync.py +179 -179
  12. package/gateway.py +220 -220
  13. package/hook_decision.py +96 -96
  14. package/index_inventory.py +75 -75
  15. package/indexer.py +878 -878
  16. package/install.py +113 -11
  17. package/install_runtime.py +101 -35
  18. package/integration_metrics.py +82 -82
  19. package/local_embedder.py +172 -172
  20. package/model_defaults.py +70 -70
  21. package/package.json +35 -35
  22. package/project_insights_ui.py +38 -38
  23. package/project_monitor.py +204 -204
  24. package/project_store.py +220 -220
  25. package/projects_ui.py +146 -146
  26. package/requirements.txt +8 -8
  27. package/research_cache.py +171 -171
  28. package/research_metrics.py +110 -110
  29. package/router.py +582 -582
  30. package/secret_store.py +121 -121
  31. package/setup_ui.py +1011 -986
  32. package/smart_tool_daemon.py +3604 -3604
  33. package/version.py +1 -1
  34. package/web_adapters/browser/fetch_camoufox.py +69 -0
  35. package/web_adapters/node/ddg-search.mjs +89 -89
  36. package/web_adapters/node/open-websearch-adapter.mjs +77 -77
  37. package/web_adapters/node/package.json +12 -12
  38. package/web_adapters/node/wikipedia-search.mjs +44 -44
  39. package/web_search_adapters.py +193 -193
  40. package/web_search_external.py +288 -288
  41. package/web_search_health.py +88 -88
@@ -1,75 +1,75 @@
1
- """Inventário somente leitura de visões, arquivos e trechos já persistidos."""
2
- import re
3
- from pathlib import Path
4
-
5
- import indexer
6
- import index_views
7
- import project_identity
8
- import document_text
9
-
10
-
11
- def views(root):
12
- key = project_identity.project_id(root)
13
- current = index_views.describe(root)
14
- paths = list(Path(indexer.INDEX_DIR).glob(key + '.v-*.sqlite3'))
15
- paths += [Path(indexer.INDEX_DIR)/(item+'.sqlite3') for item in
16
- dict.fromkeys([key, *project_identity.legacy_ids(root)])]
17
- rows = []
18
- for path in dict.fromkeys(paths):
19
- if not path.is_file() or not re.fullmatch(r'[a-f0-9]{16}(?:\.v-[a-f0-9]{16})?\.sqlite3', path.name):
20
- continue
21
- conn = indexer._readonly(str(path))
22
- try:
23
- meta = indexer._metadata(conn)
24
- view_id = meta.get('view_id') or ('legacy' if current['git'] else 'workspace')
25
- rows.append({'view_id': view_id, 'label': meta.get('view_label') or 'Legacy, no identified branch',
26
- 'branch': meta.get('git_branch'), 'commit': meta.get('git_commit'),
27
- 'current': view_id == current['view_id'], 'path': str(path),
28
- 'files': conn.execute('SELECT count(*) FROM manifest').fetchone()[0],
29
- 'chunks': conn.execute('SELECT count(*) FROM chunks').fetchone()[0],
30
- 'model': meta.get('model_id'), 'dimensions': meta.get('dimensions'),
31
- 'updated_at': meta.get('updated_at'), 'bytes': path.stat().st_size})
32
- finally:
33
- conn.close()
34
- return sorted(rows, key=lambda row: (not row['current'], row['label']))
35
-
36
-
37
- def inspect(root, view_id=None, file_path=None, storage_id=None):
38
- if file_path is not None:
39
- if not isinstance(file_path, str):
40
- raise ValueError("file_path must be a string.")
41
- file_path = file_path.replace(chr(92), "/").removeprefix("./")
42
- available = views(root)
43
- current = index_views.describe(root)
44
- explicit_view = view_id is not None or storage_id is not None
45
- view_id = view_id or current['view_id']
46
- selected = next((row for row in available if (Path(row['path']).name==storage_id if storage_id else row['view_id']==view_id)), None)
47
- if selected is None and available and not explicit_view:
48
- selected = available[0]
49
- if not selected:
50
- return {'views': available, 'selected': None, 'files': [], 'chunks': [],
51
- 'message': 'This view has not been indexed yet. Run a search or use Index now.'}
52
- conn = indexer._readonly(selected['path'])
53
- try:
54
- columns = {row[1] for row in conn.execute('PRAGMA table_info(manifest)')}
55
- # Índices anteriores ao manifest incremental não têm size/mtime_ns.
56
- # A inspeção é somente leitura; não migrar nem medir o arquivo de outra branch.
57
- size_column = 'm.size' if 'size' in columns else 'NULL'
58
- files = [{'path': path, 'chunks': count, 'hash': digest, 'size': size} for path, count, digest, size in
59
- conn.execute(f'SELECT m.path,count(c.id),m.hash,{size_column} FROM manifest m LEFT JOIN chunks c ON c.path=m.path GROUP BY m.path ORDER BY m.path LIMIT 1001')]
60
- chunks = []
61
- if file_path is not None:
62
- if not conn.execute('SELECT 1 FROM manifest WHERE path=?', (file_path,)).fetchone():
63
- raise ValueError(f'File is outside the indexed view: {file_path}')
64
- files = []
65
- chunks = [{'start_line': start, 'end_line': end, 'text': text, 'dimensions': int(size or 0)//4,
66
- 'location_kind':document_text.location_kind(file_path)}
67
- for start, end, text, size in conn.execute(
68
- 'SELECT start_line,end_line,text,length(embedding) FROM chunks WHERE path=? ORDER BY start_line LIMIT 100', (file_path,))]
69
- return {'views': available, 'selected': selected, 'files': files[:1000],
70
- 'truncated': len(files)>1000, 'chunks': chunks, 'max_chunks_displayed': 100,
71
- 'current_view': index_views.public(current),
72
- 'message': '' if selected['current'] else 'The current view is not shown. You are inspecting the stored index of ' + selected['label'] + '.',
73
- 'graph_type': 'project_branch_directory_file', 'read_only': True}
74
- finally:
75
- conn.close()
1
+ """Inventário somente leitura de visões, arquivos e trechos já persistidos."""
2
+ import re
3
+ from pathlib import Path
4
+
5
+ import indexer
6
+ import index_views
7
+ import project_identity
8
+ import document_text
9
+
10
+
11
+ def views(root):
12
+ key = project_identity.project_id(root)
13
+ current = index_views.describe(root)
14
+ paths = list(Path(indexer.INDEX_DIR).glob(key + '.v-*.sqlite3'))
15
+ paths += [Path(indexer.INDEX_DIR)/(item+'.sqlite3') for item in
16
+ dict.fromkeys([key, *project_identity.legacy_ids(root)])]
17
+ rows = []
18
+ for path in dict.fromkeys(paths):
19
+ if not path.is_file() or not re.fullmatch(r'[a-f0-9]{16}(?:\.v-[a-f0-9]{16})?\.sqlite3', path.name):
20
+ continue
21
+ conn = indexer._readonly(str(path))
22
+ try:
23
+ meta = indexer._metadata(conn)
24
+ view_id = meta.get('view_id') or ('legacy' if current['git'] else 'workspace')
25
+ rows.append({'view_id': view_id, 'label': meta.get('view_label') or 'Legacy, no identified branch',
26
+ 'branch': meta.get('git_branch'), 'commit': meta.get('git_commit'),
27
+ 'current': view_id == current['view_id'], 'path': str(path),
28
+ 'files': conn.execute('SELECT count(*) FROM manifest').fetchone()[0],
29
+ 'chunks': conn.execute('SELECT count(*) FROM chunks').fetchone()[0],
30
+ 'model': meta.get('model_id'), 'dimensions': meta.get('dimensions'),
31
+ 'updated_at': meta.get('updated_at'), 'bytes': path.stat().st_size})
32
+ finally:
33
+ conn.close()
34
+ return sorted(rows, key=lambda row: (not row['current'], row['label']))
35
+
36
+
37
+ def inspect(root, view_id=None, file_path=None, storage_id=None):
38
+ if file_path is not None:
39
+ if not isinstance(file_path, str):
40
+ raise ValueError("file_path must be a string.")
41
+ file_path = file_path.replace(chr(92), "/").removeprefix("./")
42
+ available = views(root)
43
+ current = index_views.describe(root)
44
+ explicit_view = view_id is not None or storage_id is not None
45
+ view_id = view_id or current['view_id']
46
+ selected = next((row for row in available if (Path(row['path']).name==storage_id if storage_id else row['view_id']==view_id)), None)
47
+ if selected is None and available and not explicit_view:
48
+ selected = available[0]
49
+ if not selected:
50
+ return {'views': available, 'selected': None, 'files': [], 'chunks': [],
51
+ 'message': 'This view has not been indexed yet. Run a search or use Index now.'}
52
+ conn = indexer._readonly(selected['path'])
53
+ try:
54
+ columns = {row[1] for row in conn.execute('PRAGMA table_info(manifest)')}
55
+ # Índices anteriores ao manifest incremental não têm size/mtime_ns.
56
+ # A inspeção é somente leitura; não migrar nem medir o arquivo de outra branch.
57
+ size_column = 'm.size' if 'size' in columns else 'NULL'
58
+ files = [{'path': path, 'chunks': count, 'hash': digest, 'size': size} for path, count, digest, size in
59
+ conn.execute(f'SELECT m.path,count(c.id),m.hash,{size_column} FROM manifest m LEFT JOIN chunks c ON c.path=m.path GROUP BY m.path ORDER BY m.path LIMIT 1001')]
60
+ chunks = []
61
+ if file_path is not None:
62
+ if not conn.execute('SELECT 1 FROM manifest WHERE path=?', (file_path,)).fetchone():
63
+ raise ValueError(f'File is outside the indexed view: {file_path}')
64
+ files = []
65
+ chunks = [{'start_line': start, 'end_line': end, 'text': text, 'dimensions': int(size or 0)//4,
66
+ 'location_kind':document_text.location_kind(file_path)}
67
+ for start, end, text, size in conn.execute(
68
+ 'SELECT start_line,end_line,text,length(embedding) FROM chunks WHERE path=? ORDER BY start_line LIMIT 100', (file_path,))]
69
+ return {'views': available, 'selected': selected, 'files': files[:1000],
70
+ 'truncated': len(files)>1000, 'chunks': chunks, 'max_chunks_displayed': 100,
71
+ 'current_view': index_views.public(current),
72
+ 'message': '' if selected['current'] else 'The current view is not shown. You are inspecting the stored index of ' + selected['label'] + '.',
73
+ 'graph_type': 'project_branch_directory_file', 'read_only': True}
74
+ finally:
75
+ conn.close()