Skip to content

Commit c441a31

Browse files
authored
Merge pull request #79 from vectorlessflow/dev
feat(cli): add complete CLI module structure with all commands
2 parents bdc7e4e + 747e1c5 commit c441a31

14 files changed

Lines changed: 559 additions & 0 deletions

File tree

python/vectorless/cli/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
"""Vectorless CLI — command-line interface for document intelligence."""
2+
3+
from vectorless.cli.main import app
4+
5+
__all__ = ["app"]
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
"""CLI command modules."""
2+
3+
from vectorless.cli.commands.init import init_cmd
4+
from vectorless.cli.commands.add import add_cmd
5+
from vectorless.cli.commands.list_cmd import list_cmd
6+
from vectorless.cli.commands.info import info_cmd
7+
from vectorless.cli.commands.remove import remove_cmd
8+
from vectorless.cli.commands.query import query_cmd
9+
from vectorless.cli.commands.ask import ask_cmd
10+
from vectorless.cli.commands.tree import tree_cmd
11+
from vectorless.cli.commands.stats import stats_cmd
12+
from vectorless.cli.commands.config_cmd import config_cmd
13+
14+
__all__ = [
15+
"init_cmd",
16+
"add_cmd",
17+
"list_cmd",
18+
"info_cmd",
19+
"remove_cmd",
20+
"query_cmd",
21+
"ask_cmd",
22+
"tree_cmd",
23+
"stats_cmd",
24+
"config_cmd",
25+
]
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
"""add command — index documents (maps to engine.index)."""
2+
3+
from typing import Optional
4+
5+
import click
6+
7+
8+
def add_cmd(
9+
path: str,
10+
*,
11+
recursive: bool = False,
12+
fmt: Optional[str] = None,
13+
force: bool = False,
14+
jobs: int = 1,
15+
verbose: bool = False,
16+
) -> None:
17+
"""Index a document or directory.
18+
19+
Args:
20+
path: File or directory path.
21+
recursive: Index directory recursively.
22+
fmt: Force format ("markdown" | "pdf" | None for auto-detect).
23+
force: Force re-index existing documents.
24+
jobs: Number of parallel indexing jobs.
25+
verbose: Show detailed progress.
26+
27+
Uses:
28+
Engine.index(IndexContext)
29+
IndexContext.from_path / from_paths / from_dir
30+
IndexOptions(mode="force" if force else "default")
31+
"""
32+
raise NotImplementedError
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
"""ask command — interactive REPL for multi-turn queries."""
2+
3+
from typing import Optional
4+
5+
import click
6+
7+
8+
def ask_cmd(*, doc_id: Optional[str] = None, verbose: bool = False) -> None:
9+
"""Start an interactive query REPL.
10+
11+
Args:
12+
doc_id: Limit to a specific document.
13+
verbose: Show Agent navigation steps.
14+
15+
Uses:
16+
Engine.query() in a loop with user input.
17+
Maintains conversation context across turns.
18+
19+
Built-in commands (prefixed with .):
20+
.help Show available commands
21+
.tree Display current document tree
22+
.stats Show session statistics (LLM calls, tokens, cost)
23+
.nav-log Show navigation log for current conversation
24+
.doc <id> Switch query target document
25+
.doc Show current target document
26+
.verbose Toggle verbose mode
27+
.quit Exit REPL
28+
"""
29+
raise NotImplementedError
30+
31+
32+
def _handle_repl_command(line: str) -> bool:
33+
"""Handle a built-in REPL command (prefixed with .).
34+
35+
Args:
36+
line: Raw input line.
37+
38+
Returns:
39+
True if the command was handled, False if it's a query.
40+
"""
41+
raise NotImplementedError
42+
43+
44+
def _print_welcome() -> None:
45+
"""Print REPL welcome message with available commands."""
46+
raise NotImplementedError
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
"""config command — view and modify configuration."""
2+
3+
from typing import Optional
4+
5+
import click
6+
7+
8+
def config_cmd(
9+
key: Optional[str] = None,
10+
value: Optional[str] = None,
11+
*,
12+
init_config: bool = False,
13+
) -> None:
14+
"""View or modify workspace configuration.
15+
16+
Args:
17+
key: Config key (dot-separated, e.g. "llm.model").
18+
value: New value to set. If None, prints current value.
19+
init_config: Reset config to defaults.
20+
21+
Usage:
22+
vectorless-cli config # show all
23+
vectorless-cli config llm.model # show one key
24+
vectorless-cli config llm.model gpt-4o # set value
25+
vectorless-cli config --init # reset defaults
26+
27+
Config keys (in .vectorless/config.toml):
28+
llm.model LLM model name
29+
llm.api_key API key (or env VECTORLESS_API_KEY)
30+
llm.endpoint API endpoint
31+
retrieval.strategy agent | pipeline
32+
retrieval.max_rounds navigation budget
33+
index.summary full | selective | lazy | navigation
34+
index.compact_mode true | false
35+
"""
36+
raise NotImplementedError
37+
38+
39+
def _load_config(workspace: str) -> dict:
40+
"""Load config.toml from workspace.
41+
42+
Args:
43+
workspace: Path to .vectorless/ directory.
44+
45+
Returns:
46+
Parsed config dict.
47+
"""
48+
raise NotImplementedError
49+
50+
51+
def _save_config(workspace: str, config: dict) -> None:
52+
"""Save config dict to config.toml.
53+
54+
Args:
55+
workspace: Path to .vectorless/ directory.
56+
config: Config dict to serialize.
57+
"""
58+
raise NotImplementedError
59+
60+
61+
def _default_config() -> dict:
62+
"""Return default configuration values."""
63+
raise NotImplementedError
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
"""info command — show document index details."""
2+
3+
import click
4+
5+
6+
def info_cmd(doc_id: str) -> None:
7+
"""Show detailed information about an indexed document.
8+
9+
Args:
10+
doc_id: Document identifier.
11+
12+
Uses:
13+
Engine.list() -> filter by doc_id
14+
Display: title, source, format, node count, depth, leaf count,
15+
total tokens, routing keywords, top-level sections,
16+
indexed timestamp.
17+
18+
Example output:
19+
Document: API Guide (a1b2c3)
20+
Source: ./docs/api-guide.md
21+
Format: Markdown
22+
Tree: 45 nodes, depth 4, 12 leaves
23+
Total tokens: 8,234
24+
Routing keywords: api, authentication, endpoints, rate-limit
25+
Top-level sections:
26+
1. Overview (12 leaves)
27+
2. Authentication (8 leaves)
28+
3. Endpoints (18 leaves)
29+
"""
30+
raise NotImplementedError
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
"""init command — initialize .vectorless/ workspace."""
2+
3+
import click
4+
5+
6+
def init_cmd(workspace: str) -> None:
7+
"""Create .vectorless/ directory structure with default config.
8+
9+
Creates:
10+
.vectorless/
11+
├── config.toml # LLM key/model/endpoint, retrieval strategy
12+
├── data/ # Index data (DocumentTree, ReasoningIndex)
13+
└── cache/ # Memo cache
14+
15+
Args:
16+
workspace: Parent directory to create .vectorless/ in.
17+
"""
18+
raise NotImplementedError
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
"""list command — list indexed documents."""
2+
3+
import click
4+
5+
6+
def list_cmd(*, fmt: str = "table") -> None:
7+
"""List all indexed documents in the workspace.
8+
9+
Args:
10+
fmt: Output format — "table" or "json".
11+
12+
Uses:
13+
Engine.list() -> List[DocumentInfo]
14+
15+
Table output:
16+
Doc ID | Title | Format | Nodes | Pages | Indexed At
17+
"""
18+
raise NotImplementedError
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
"""query command — single query (maps to engine.query)."""
2+
3+
from typing import Optional
4+
5+
import click
6+
7+
8+
def query_cmd(
9+
question: str,
10+
*,
11+
doc_ids: tuple[str, ...] = (),
12+
workspace_scope: bool = False,
13+
fmt: str = "text",
14+
verbose: bool = False,
15+
max_tokens: Optional[int] = None,
16+
) -> None:
17+
"""Execute a single query against indexed documents.
18+
19+
Args:
20+
question: Natural-language question.
21+
doc_ids: Limit to specific document IDs.
22+
workspace_scope: Query across all documents.
23+
fmt: Output format — "text" or "json".
24+
verbose: Show Agent navigation steps.
25+
max_tokens: Max result tokens.
26+
27+
Uses:
28+
Engine.query(QueryContext(question)
29+
.with_doc_ids([...]) or .with_workspace()
30+
.with_max_tokens(n))
31+
-> QueryResult
32+
33+
Verbose mode prints Agent navigation:
34+
[1/8] Bird's-eye: 3 top-level branches
35+
[2/8] Descend → payment-configuration
36+
[3/8] GetContent → doc 29139b
37+
[4/8] Evaluate → sufficient
38+
→ Answer: ...
39+
"""
40+
raise NotImplementedError
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
"""remove command — remove document index."""
2+
3+
import click
4+
5+
6+
def remove_cmd(doc_id: str) -> None:
7+
"""Remove a document from the index.
8+
9+
Args:
10+
doc_id: Document identifier to remove.
11+
12+
Uses:
13+
Engine.remove(doc_id)
14+
"""
15+
raise NotImplementedError

0 commit comments

Comments
 (0)