Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 7 additions & 1 deletion packages/cli/src/repowise/cli/commands/init_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -977,6 +977,7 @@ def init_command(

# Merge exclude_patterns from config.yaml and --exclude/-x flags
config = load_config(repo_path)
language = config.get("language", "en")
exclude_patterns: list[str] = list(config.get("exclude_patterns") or []) + list(exclude)

# Resolve commit limit: CLI flag → config.yaml → default (500)
Expand Down Expand Up @@ -1038,6 +1039,8 @@ def init_command(
f" Provider: [cyan]{provider.provider_name}[/cyan] / Model: [cyan]{provider.model_name}[/cyan]"
)
console.print(f" Embedder: [cyan]{embedder_name_resolved}[/cyan]")
if language != "en":
console.print(f" Language: [cyan]{language}[/cyan]")

# Validate provider connection
from repowise.core.providers.llm.base import ProviderError
Expand Down Expand Up @@ -1150,7 +1153,9 @@ def init_command(
# Cost estimation
from repowise.core.generation import GenerationConfig

gen_config = GenerationConfig(max_concurrency=concurrency)
cfg = load_config(repo_path)
language = cfg.get("language", "en")
gen_config = GenerationConfig(max_concurrency=concurrency, language=language)
plans = build_generation_plan(
result.parsed_files, result.graph_builder, gen_config, skip_tests, skip_infra
)
Expand Down Expand Up @@ -1291,6 +1296,7 @@ async def _make_cost_tracker() -> CostTracker:
progress=gen_callback,
resume=resume,
cost_tracker=cost_tracker,
generation_config=gen_config,
)
)

Expand Down
4 changes: 3 additions & 1 deletion packages/cli/src/repowise/cli/commands/update_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,9 @@ def update_command(
from repowise.core.generation import ContextAssembler, GenerationConfig, PageGenerator
from repowise.core.ingestion import ASTParser, FileTraverser, GraphBuilder

config = GenerationConfig()
cfg = load_config(repo_path)
language = cfg.get("language", "en")
config = GenerationConfig(max_concurrency=concurrency, language=language)()

# Read exclude patterns from config (set during init or via web UI)
repo_config = load_config(repo_path)
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/repowise/core/generation/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ class GenerationConfig:
max_pages_pct: float = 0.10 # hard cap: total pages ≤ max(50, N_files * this)
jobs_dir: str = ".repowise/jobs"
large_file_source_pct: float = 0.4 # use structural summary when source tokens > budget * this

language: str = "en"

# ---------------------------------------------------------------------------
# GeneratedPage
Expand Down
23 changes: 17 additions & 6 deletions packages/core/src/repowise/core/generation/page_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,12 +154,14 @@ def __init__(
assembler: ContextAssembler,
config: GenerationConfig,
jinja_env: jinja2.Environment | None = None,
vector_store: Any | None = None, # VectorStore | None
vector_store: Any | None = None,
language: str = "en",
) -> None:
self._provider = provider
self._assembler = assembler
self._config = config
self._vector_store = vector_store
self._language = language
self._cache: dict[str, GeneratedResponse] = {}

if jinja_env is None:
Expand All @@ -171,7 +173,6 @@ def __init__(
autoescape=False,
)
self._jinja_env = jinja_env

# ------------------------------------------------------------------
# Per-type generation methods
# ------------------------------------------------------------------
Expand Down Expand Up @@ -929,21 +930,31 @@ async def _generate_file_page_from_ctx(
)
page.metadata["hallucination_warnings"] = hal_warnings
return page

async def _call_provider(
self,
page_type: str,
user_prompt: str,
request_id: str,
) -> GeneratedResponse:
"""Call the provider with caching."""
key = self._compute_cache_key(page_type, user_prompt)
if self._config.cache_enabled and key in self._cache:
log.debug("Cache hit", page_type=page_type, key=key[:8])
return self._cache[key]

base_system = SYSTEM_PROMPTS[page_type]
if self._language != "en":
language_instruction = (
f"Generate all documentation content in {self._language}. "
"Keep all code, file paths, and symbol names in their original form. "
"Do not translate them.\n\n"
)
system_prompt = language_instruction + base_system
else:
system_prompt = base_system

response = await self._provider.generate(
SYSTEM_PROMPTS[page_type],
system_prompt,
user_prompt,
max_tokens=self._config.max_tokens,
temperature=self._config.temperature,
Expand All @@ -954,7 +965,7 @@ async def _call_provider(
self._cache[key] = response

return response

def _compute_cache_key(self, page_type: str, user_prompt: str) -> str:
"""Return SHA256(model + page_type + user_prompt) as cache key."""
raw = f"{self._provider.model_name}:{page_type}:{user_prompt}"
Expand Down
31 changes: 27 additions & 4 deletions packages/core/src/repowise/core/pipeline/orchestrator.py
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,7 @@ async def run_generation(
progress: ProgressCallback | None,
resume: bool = False,
cost_tracker: Any | None = None,
generation_config: Any, # <-- ДОБАВЛЕННЫЙ ПАРАМЕТР
) -> list[Any]:
"""Run LLM-powered page generation.

Expand All @@ -741,7 +742,23 @@ async def run_generation(
if cost_tracker is not None and llm_client is not None and hasattr(llm_client, "_cost_tracker"):
llm_client._cost_tracker = cost_tracker

config = GenerationConfig(max_concurrency=concurrency)
# Создаём новый конфиг на основе переданного generation_config, но с нужным max_concurrency
config = GenerationConfig(
max_tokens=generation_config.max_tokens,
temperature=generation_config.temperature,
token_budget=generation_config.token_budget,
max_concurrency=concurrency,
cache_enabled=generation_config.cache_enabled,
staleness_threshold_days=generation_config.staleness_threshold_days,
expiry_threshold_days=generation_config.expiry_threshold_days,
top_symbol_percentile=generation_config.top_symbol_percentile,
file_page_top_percentile=generation_config.file_page_top_percentile,
file_page_min_symbols=generation_config.file_page_min_symbols,
max_pages_pct=generation_config.max_pages_pct,
jobs_dir=generation_config.jobs_dir,
large_file_source_pct=generation_config.large_file_source_pct,
language=generation_config.language,
)
assembler = ContextAssembler(config)

# Resolve embedder and vector store
Expand All @@ -750,8 +767,6 @@ async def run_generation(
if vector_store is None:
vector_store = InMemoryVectorStore(embedder_impl)

generator = PageGenerator(llm_client, assembler, config, vector_store=vector_store)

# Job system — use a temp-like dir under repo_path for checkpoints
jobs_dir = repo_path / ".repowise" / "jobs"
jobs_dir.mkdir(parents=True, exist_ok=True)
Expand All @@ -778,6 +793,14 @@ def on_total_known(total: int) -> None:
if progress:
progress.on_phase_start("generation", total)

generator = PageGenerator(
llm_client,
assembler,
config,
vector_store=vector_store,
language=config.language,
)

generated_pages = await generator.generate_all(
parsed_files,
source_map,
Expand All @@ -795,4 +818,4 @@ def on_total_known(total: int) -> None:
if progress:
progress.on_message("info", f"Generated {len(generated_pages)} pages")

return generated_pages
return generated_pages