vectorgov-cli 0.3.0__tar.gz → 0.3.2__tar.gz

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 (30) hide show
  1. {vectorgov_cli-0.3.0 → vectorgov_cli-0.3.2}/.gitignore +4 -3
  2. {vectorgov_cli-0.3.0 → vectorgov_cli-0.3.2}/PKG-INFO +17 -2
  3. {vectorgov_cli-0.3.0 → vectorgov_cli-0.3.2}/README.md +16 -1
  4. {vectorgov_cli-0.3.0 → vectorgov_cli-0.3.2}/pyproject.toml +1 -1
  5. {vectorgov_cli-0.3.0 → vectorgov_cli-0.3.2}/src/vectorgov/cli/__init__.py +1 -1
  6. {vectorgov_cli-0.3.0 → vectorgov_cli-0.3.2}/src/vectorgov/cli/commands/__init__.py +4 -1
  7. {vectorgov_cli-0.3.0 → vectorgov_cli-0.3.2}/src/vectorgov/cli/commands/ask.py +1 -3
  8. {vectorgov_cli-0.3.0 → vectorgov_cli-0.3.2}/src/vectorgov/cli/commands/context.py +0 -2
  9. {vectorgov_cli-0.3.0 → vectorgov_cli-0.3.2}/src/vectorgov/cli/commands/docs.py +2 -2
  10. {vectorgov_cli-0.3.0 → vectorgov_cli-0.3.2}/src/vectorgov/cli/commands/explain.py +3 -5
  11. {vectorgov_cli-0.3.0 → vectorgov_cli-0.3.2}/src/vectorgov/cli/commands/fs_search.py +4 -7
  12. {vectorgov_cli-0.3.0 → vectorgov_cli-0.3.2}/src/vectorgov/cli/commands/grep_cmd.py +3 -6
  13. {vectorgov_cli-0.3.0 → vectorgov_cli-0.3.2}/src/vectorgov/cli/commands/hybrid.py +4 -6
  14. {vectorgov_cli-0.3.0 → vectorgov_cli-0.3.2}/src/vectorgov/cli/commands/init.py +225 -227
  15. {vectorgov_cli-0.3.0 → vectorgov_cli-0.3.2}/src/vectorgov/cli/commands/lookup.py +2 -4
  16. {vectorgov_cli-0.3.0 → vectorgov_cli-0.3.2}/src/vectorgov/cli/commands/merged.py +3 -6
  17. {vectorgov_cli-0.3.0 → vectorgov_cli-0.3.2}/src/vectorgov/cli/commands/quota.py +130 -132
  18. {vectorgov_cli-0.3.0 → vectorgov_cli-0.3.2}/src/vectorgov/cli/commands/read.py +0 -2
  19. {vectorgov_cli-0.3.0 → vectorgov_cli-0.3.2}/src/vectorgov/cli/commands/search.py +0 -2
  20. {vectorgov_cli-0.3.0 → vectorgov_cli-0.3.2}/src/vectorgov/cli/commands/smart_search.py +3 -5
  21. {vectorgov_cli-0.3.0 → vectorgov_cli-0.3.2}/src/vectorgov/cli/commands/tokens.py +0 -2
  22. {vectorgov_cli-0.3.0 → vectorgov_cli-0.3.2}/src/vectorgov/cli/main.py +21 -16
  23. {vectorgov_cli-0.3.0 → vectorgov_cli-0.3.2}/src/vectorgov/cli/utils/output.py +131 -22
  24. {vectorgov_cli-0.3.0 → vectorgov_cli-0.3.2}/src/vectorgov/cli/commands/audit.py +0 -0
  25. {vectorgov_cli-0.3.0 → vectorgov_cli-0.3.2}/src/vectorgov/cli/commands/auth.py +0 -0
  26. {vectorgov_cli-0.3.0 → vectorgov_cli-0.3.2}/src/vectorgov/cli/commands/config.py +0 -0
  27. {vectorgov_cli-0.3.0 → vectorgov_cli-0.3.2}/src/vectorgov/cli/commands/feedback.py +0 -0
  28. {vectorgov_cli-0.3.0 → vectorgov_cli-0.3.2}/src/vectorgov/cli/commands/prompts.py +0 -0
  29. {vectorgov_cli-0.3.0 → vectorgov_cli-0.3.2}/src/vectorgov/cli/utils/__init__.py +0 -0
  30. {vectorgov_cli-0.3.0 → vectorgov_cli-0.3.2}/src/vectorgov/cli/utils/config.py +0 -0
@@ -12,6 +12,7 @@ __pycache__/
12
12
  # Virtual environments
13
13
  venv/
14
14
  .venv/
15
+ .venv-test/
15
16
  env/
16
17
 
17
18
  # IDE
@@ -23,6 +24,6 @@ env/
23
24
  # OS
24
25
  .DS_Store
25
26
  Thumbs.db
26
-
27
- # Test notebooks (may contain API keys)
28
- test_cli_commands.ipynb
27
+
28
+ # Test notebooks (may contain API keys)
29
+ test_cli_commands.ipynb
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vectorgov-cli
3
- Version: 0.3.0
3
+ Version: 0.3.2
4
4
  Summary: CLI para a API VectorGov - Busca semântica em legislação brasileira
5
5
  Project-URL: Homepage, https://vectorgov.io
6
6
  Project-URL: Documentation, https://vectorgov.io/documentacao
@@ -60,7 +60,17 @@ Cliente de linha de comando para a API VectorGov - Busca semântica em legislaç
60
60
  [![Python versions](https://img.shields.io/pypi/pyversions/vectorgov-cli.svg)](https://pypi.org/project/vectorgov-cli/)
61
61
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
62
62
 
63
- ## Para LLMs e agentes de IA (v0.2.3)
63
+ > **Novo em 0.3.2** zero truncamento de conteúdo em todos os formatos
64
+ > de saída + TTY detection automática: quando stdout não é terminal
65
+ > (pipe, LLM, CI/CD), o formato padrão vira `llm` automaticamente. A
66
+ > tabela do `search` ganhou coluna `Norma` para identificar de qual lei
67
+ > cada artigo veio. Veja o [CHANGELOG](CHANGELOG.md#032---2026-04-15).
68
+ >
69
+ > **Novo em 0.3.1** — parsing GNU-style: flags e argumentos funcionam em
70
+ > qualquer ordem (`search "ETP" --top-k 3` e `search --top-k 3 "ETP"`
71
+ > fazem a mesma coisa).
72
+
73
+ ## Para LLMs e agentes de IA (v0.3.2+)
64
74
 
65
75
  Se voce e um LLM ou agente de IA usando o CLI do VectorGov em sessoes
66
76
  de vibe coding, estas features foram projetadas para voce:
@@ -198,6 +208,11 @@ export VECTORGOV_API_KEY="vg_sua_chave"
198
208
 
199
209
  ## Uso
200
210
 
211
+ > **Ordem de argumentos**: o CLI aceita flags e argumentos posicionais em
212
+ > qualquer ordem (estilo GNU, igual a `git`, `curl`, `kubectl`, `npm`).
213
+ > `vectorgov search "ETP" --top-k 3` e `vectorgov search --top-k 3 "ETP"`
214
+ > produzem o mesmo resultado. Use o estilo que preferir.
215
+
201
216
  ### Busca
202
217
 
203
218
  ```bash
@@ -7,7 +7,17 @@ Cliente de linha de comando para a API VectorGov - Busca semântica em legislaç
7
7
  [![Python versions](https://img.shields.io/pypi/pyversions/vectorgov-cli.svg)](https://pypi.org/project/vectorgov-cli/)
8
8
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
9
9
 
10
- ## Para LLMs e agentes de IA (v0.2.3)
10
+ > **Novo em 0.3.2** zero truncamento de conteúdo em todos os formatos
11
+ > de saída + TTY detection automática: quando stdout não é terminal
12
+ > (pipe, LLM, CI/CD), o formato padrão vira `llm` automaticamente. A
13
+ > tabela do `search` ganhou coluna `Norma` para identificar de qual lei
14
+ > cada artigo veio. Veja o [CHANGELOG](CHANGELOG.md#032---2026-04-15).
15
+ >
16
+ > **Novo em 0.3.1** — parsing GNU-style: flags e argumentos funcionam em
17
+ > qualquer ordem (`search "ETP" --top-k 3` e `search --top-k 3 "ETP"`
18
+ > fazem a mesma coisa).
19
+
20
+ ## Para LLMs e agentes de IA (v0.3.2+)
11
21
 
12
22
  Se voce e um LLM ou agente de IA usando o CLI do VectorGov em sessoes
13
23
  de vibe coding, estas features foram projetadas para voce:
@@ -145,6 +155,11 @@ export VECTORGOV_API_KEY="vg_sua_chave"
145
155
 
146
156
  ## Uso
147
157
 
158
+ > **Ordem de argumentos**: o CLI aceita flags e argumentos posicionais em
159
+ > qualquer ordem (estilo GNU, igual a `git`, `curl`, `kubectl`, `npm`).
160
+ > `vectorgov search "ETP" --top-k 3` e `vectorgov search --top-k 3 "ETP"`
161
+ > produzem o mesmo resultado. Use o estilo que preferir.
162
+
148
163
  ### Busca
149
164
 
150
165
  ```bash
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "vectorgov-cli"
7
- version = "0.3.0"
7
+ version = "0.3.2"
8
8
  description = "CLI para a API VectorGov - Busca semântica em legislação brasileira"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -7,7 +7,7 @@ Uso:
7
7
  vectorgov auth login
8
8
  """
9
9
 
10
- __version__ = "0.3.0"
10
+ __version__ = "0.3.2"
11
11
 
12
12
  from .main import app
13
13
 
@@ -4,7 +4,7 @@ Comandos do CLI VectorGov.
4
4
 
5
5
  from . import auth, search, ask, feedback, docs, config, tokens
6
6
  from . import smart_search, hybrid, lookup, grep_cmd, merged, audit, quota, prompts
7
- from . import context, init
7
+ from . import context, init, fs_search, read, explain
8
8
 
9
9
  __all__ = [
10
10
  "auth",
@@ -24,4 +24,7 @@ __all__ = [
24
24
  "prompts",
25
25
  "context",
26
26
  "init",
27
+ "fs_search",
28
+ "read",
29
+ "explain",
27
30
  ]
@@ -17,7 +17,6 @@ from rich.syntax import Syntax
17
17
  from ..utils.config import ConfigManager
18
18
  from ..utils.output import OutputFormat, extract_request_id, print_request_id_footer
19
19
 
20
- app = typer.Typer()
21
20
  console = Console()
22
21
  config_manager = ConfigManager()
23
22
 
@@ -43,7 +42,6 @@ def _check_admin(api_key: str) -> bool:
43
42
  return False
44
43
 
45
44
 
46
- @app.callback(invoke_without_command=True)
47
45
  def ask(
48
46
  query: str = typer.Argument(..., help="Pergunta em linguagem natural"),
49
47
  top_k: int = typer.Option(5, "--top-k", "-k", help="Número de chunks para contexto"),
@@ -150,7 +148,7 @@ def ask(
150
148
  for i, hit in enumerate(results.hits, 1):
151
149
  title = f"[bold]#{i}[/bold] Art. {hit.article_number} ({getattr(hit, 'document_id', None) or getattr(hit, 'source', '')})"
152
150
  console.print(Panel(
153
- hit.text[:500] + ("..." if len(hit.text) > 500 else ""),
151
+ hit.text,
154
152
  title=title,
155
153
  border_style="blue"
156
154
  ))
@@ -8,12 +8,10 @@ from rich.console import Console
8
8
  from ..utils.config import ConfigManager
9
9
  from ..utils.output import extract_request_id, print_request_id_footer
10
10
 
11
- app = typer.Typer()
12
11
  console = Console()
13
12
  config_manager = ConfigManager()
14
13
 
15
14
 
16
- @app.callback(invoke_without_command=True)
17
15
  def context(
18
16
  query: str = typer.Argument(..., help="Pergunta jurídica"),
19
17
  top_k: int = typer.Option(5, "--top-k", "-k", help="Quantidade de resultados (1-20)"),
@@ -120,7 +120,7 @@ def list_docs(
120
120
  else:
121
121
  table = Table(title="Documentos Disponíveis")
122
122
  table.add_column("ID", style="cyan")
123
- table.add_column("Título")
123
+ table.add_column("Título", overflow="fold")
124
124
  table.add_column("Tipo", style="green")
125
125
  table.add_column("Ano", justify="right")
126
126
  table.add_column("Chunks", justify="right")
@@ -135,7 +135,7 @@ def list_docs(
135
135
  chunks = getattr(d, "chunks_count", 0)
136
136
  table.add_row(
137
137
  str(doc_id),
138
- titulo[:50] + "..." if len(str(titulo)) > 50 else str(titulo),
138
+ str(titulo),
139
139
  str(tipo),
140
140
  str(ano),
141
141
  str(chunks),
@@ -13,12 +13,10 @@ from ..utils.output import (
13
13
  render_llm_output,
14
14
  )
15
15
 
16
- app = typer.Typer()
17
16
  console = Console()
18
17
  config_manager = ConfigManager()
19
18
 
20
19
 
21
- @app.callback(invoke_without_command=True)
22
20
  def explain(
23
21
  reference: str = typer.Argument(..., help="Referencia legal (ex: 'Art. 75 da Lei 14.133')"),
24
22
  output: str = typer.Option("llm", "--output", "-o", help="Formato: llm, text, json, raw"),
@@ -158,7 +156,7 @@ def explain(
158
156
  lines.append(main_text)
159
157
  if parent_text:
160
158
  lines.append("")
161
- lines.append(f"PARENT: {parent_text[:200]}")
159
+ lines.append(f"PARENT: {parent_text}")
162
160
  else:
163
161
  lines.append("")
164
162
  lines.append("PARENT: (nenhum -- dispositivo de primeiro nivel)")
@@ -199,10 +197,10 @@ def explain(
199
197
  console.print(f"\nStatus: [green]{status}[/green]")
200
198
  console.print(Panel(main_text, title=title, border_style="cyan"))
201
199
  if parent_text:
202
- console.print(f"[dim]Parent: {parent_text[:150]}...[/dim]")
200
+ console.print(Panel(parent_text, title="Parent", border_style="dim"))
203
201
  console.print(f"[dim]Filhos: {children_count} dispositivos[/dim]")
204
202
  if nota:
205
- console.print(f"\n[bold]Nota do especialista:[/bold] {nota[:200]}")
203
+ console.print(f"\n[bold]Nota do especialista:[/bold] {nota}")
206
204
  if evidence_url:
207
205
  console.print(f"[dim] Ver trecho: {evidence_url}[/dim]")
208
206
  if document_url:
@@ -14,12 +14,10 @@ from ..utils.output import (
14
14
  resolve_output_format,
15
15
  )
16
16
 
17
- app = typer.Typer()
18
17
  console = Console()
19
18
  config_manager = ConfigManager()
20
19
 
21
20
 
22
- @app.callback(invoke_without_command=True)
23
21
  def fs_search(
24
22
  query: str = typer.Argument(..., help="Pergunta ou termo para buscar"),
25
23
  document_id: str = typer.Option(None, "--doc", "-d", help="Filtrar por documento (ex: LEI-14133-2021)"),
@@ -117,7 +115,7 @@ def fs_search(
117
115
  {
118
116
  "source": getattr(h, "source", ""),
119
117
  "score": getattr(h, "score", 0),
120
- "text": getattr(h, "text", str(h))[:300],
118
+ "text": getattr(h, "text", str(h)),
121
119
  "breadcrumb": getattr(h, "breadcrumb", ""),
122
120
  }
123
121
  for h in hits
@@ -128,17 +126,16 @@ def fs_search(
128
126
  table = Table(title=f"Filesystem Search ({len(hits)} resultados)")
129
127
  table.add_column("#", style="dim", width=3)
130
128
  table.add_column("Fonte", style="cyan", width=30)
131
- table.add_column("Texto", width=65)
129
+ table.add_column("Texto", overflow="fold")
132
130
  table.add_column("Score", justify="right", width=6)
133
131
  table.add_column("Motivo", width=10)
134
132
  for i, h in enumerate(hits, 1):
135
133
  source = getattr(h, "source", getattr(h, "document_id", ""))
136
134
  score = getattr(h, "score", 0)
137
135
  text = getattr(h, "text", str(h))
138
- text = text[:160] + "..." if len(text) > 160 else text
139
136
  reason = getattr(h, "match_reason", "")
140
137
  table.add_row(
141
- str(i), source, text, f"{score:.2f}" if score else "-", reason[:10]
138
+ str(i), source, text, f"{score:.2f}" if score else "-", reason
142
139
  )
143
140
  console.print(table)
144
141
  else:
@@ -148,7 +145,7 @@ def fs_search(
148
145
  console.print(f"\n[cyan][{i}][/cyan] [bold]{source}[/bold]")
149
146
  if breadcrumb:
150
147
  console.print(f" [dim]{breadcrumb}[/dim]")
151
- console.print(f" {getattr(h, 'text', str(h))[:300]}")
148
+ console.print(f" {getattr(h, 'text', str(h))}")
152
149
  for line in render_evidence_lines_text(h):
153
150
  console.print(f"[dim]{line}[/dim]")
154
151
 
@@ -14,12 +14,10 @@ from ..utils.output import (
14
14
  resolve_output_format,
15
15
  )
16
16
 
17
- app = typer.Typer()
18
17
  console = Console()
19
18
  config_manager = ConfigManager()
20
19
 
21
20
 
22
- @app.callback(invoke_without_command=True)
23
21
  def grep(
24
22
  query: str = typer.Argument(..., help="Texto exato para buscar (ex: 'dispensa de licitação')"),
25
23
  document_id: str = typer.Option(None, "--doc", "-d", help="Filtrar por documento (ex: LEI-14.133-2021)"),
@@ -109,7 +107,7 @@ def grep(
109
107
  "request_id": extract_request_id(result),
110
108
  "hits": [
111
109
  {"source": getattr(h, "source", ""), "span_id": getattr(h, "span_id", ""),
112
- "text": getattr(h, "text", str(h))[:300]}
110
+ "text": getattr(h, "text", str(h))}
113
111
  for h in hits
114
112
  ],
115
113
  }
@@ -118,18 +116,17 @@ def grep(
118
116
  table = Table(title=f"grep: '{query}'")
119
117
  table.add_column("#", style="dim", width=3)
120
118
  table.add_column("Fonte", style="cyan", width=30)
121
- table.add_column("Trecho", width=80)
119
+ table.add_column("Trecho", overflow="fold")
122
120
  for i, h in enumerate(hits, 1):
123
121
  source = getattr(h, "source", getattr(h, "document_id", ""))
124
122
  text = getattr(h, "text", str(h))
125
- text = text[:200] + "..." if len(text) > 200 else text
126
123
  table.add_row(str(i), source, text)
127
124
  console.print(table)
128
125
  else:
129
126
  for i, h in enumerate(hits, 1):
130
127
  source = getattr(h, "source", getattr(h, "document_id", ""))
131
128
  console.print(f"[cyan][{i}][/cyan] [bold]{source}[/bold]")
132
- console.print(f" {getattr(h, 'text', str(h))[:300]}")
129
+ console.print(f" {getattr(h, 'text', str(h))}")
133
130
  for line in render_evidence_lines_text(h):
134
131
  console.print(f"[dim]{line}[/dim]")
135
132
  console.print()
@@ -14,12 +14,10 @@ from ..utils.output import (
14
14
  resolve_output_format,
15
15
  )
16
16
 
17
- app = typer.Typer()
18
17
  console = Console()
19
18
  config_manager = ConfigManager()
20
19
 
21
20
 
22
- @app.callback(invoke_without_command=True)
23
21
  def hybrid(
24
22
  query: str = typer.Argument(..., help="Pergunta jurídica"),
25
23
  top_k: int = typer.Option(10, "--top-k", "-k", help="Quantidade de resultados (1-50)"),
@@ -143,7 +141,7 @@ def hybrid(
143
141
  {
144
142
  "source": getattr(h, "source", ""),
145
143
  "score": getattr(h, "score", 0),
146
- "text": h.text[:300],
144
+ "text": h.text,
147
145
  "graph": getattr(h, "is_graph_expanded", False),
148
146
  }
149
147
  for h in hits
@@ -153,13 +151,13 @@ def hybrid(
153
151
  table = Table(title=f"Busca Híbrida ({len(hits)} resultados)")
154
152
  table.add_column("#", style="dim", width=3)
155
153
  table.add_column("Fonte", style="cyan", width=30)
156
- table.add_column("Texto", width=70)
154
+ table.add_column("Texto", overflow="fold")
157
155
  table.add_column("Score", justify="right", width=6)
158
156
  table.add_column("Grafo", width=5)
159
157
  for i, h in enumerate(hits, 1):
160
158
  source = getattr(h, "source", getattr(h, "document_id", ""))
161
159
  score = getattr(h, "score", 0)
162
- text = h.text[:180] + "..." if len(h.text) > 180 else h.text
160
+ text = h.text
163
161
  graph = "+" if getattr(h, "is_graph_expanded", False) else ""
164
162
  table.add_row(
165
163
  str(i), source, text, f"{score:.2f}" if score else "-", graph
@@ -174,7 +172,7 @@ def hybrid(
174
172
  else ""
175
173
  )
176
174
  console.print(f"\n[cyan][{i}][/cyan] [bold]{source}[/bold]{graph_tag}")
177
- console.print(f" {h.text[:300]}")
175
+ console.print(f" {h.text}")
178
176
  for line in render_evidence_lines_text(h):
179
177
  console.print(f"[dim]{line}[/dim]")
180
178