docwright 0.1.4__tar.gz → 0.1.6__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 (43) hide show
  1. {docwright-0.1.4 → docwright-0.1.6}/PKG-INFO +1 -1
  2. {docwright-0.1.4 → docwright-0.1.6}/docwright/cli.py +87 -1
  3. {docwright-0.1.4 → docwright-0.1.6}/docwright/config.py +3 -1
  4. {docwright-0.1.4 → docwright-0.1.6}/docwright/engine.py +1 -1
  5. docwright-0.1.6/docwright/outputs/factory.py +24 -0
  6. docwright-0.1.6/docwright/outputs/gitlab_wiki.py +36 -0
  7. {docwright-0.1.4 → docwright-0.1.6}/pyproject.toml +1 -1
  8. docwright-0.1.4/docwright/outputs/factory.py +0 -12
  9. {docwright-0.1.4 → docwright-0.1.6}/LICENSE +0 -0
  10. {docwright-0.1.4 → docwright-0.1.6}/README.md +0 -0
  11. {docwright-0.1.4 → docwright-0.1.6}/docwright/__init__.py +0 -0
  12. {docwright-0.1.4 → docwright-0.1.6}/docwright/analyzer.py +0 -0
  13. {docwright-0.1.4 → docwright-0.1.6}/docwright/built_in_templates/__init__.py +0 -0
  14. {docwright-0.1.4 → docwright-0.1.6}/docwright/built_in_templates/readme/__init__.py +0 -0
  15. {docwright-0.1.4 → docwright-0.1.6}/docwright/built_in_templates/readme/default.md.j2 +0 -0
  16. {docwright-0.1.4 → docwright-0.1.6}/docwright/built_in_templates/wiki/__init__.py +0 -0
  17. {docwright-0.1.4 → docwright-0.1.6}/docwright/built_in_templates/wiki/adr.md.j2 +0 -0
  18. {docwright-0.1.4 → docwright-0.1.6}/docwright/built_in_templates/wiki/api-contracts.md.j2 +0 -0
  19. {docwright-0.1.4 → docwright-0.1.6}/docwright/built_in_templates/wiki/architecture.md.j2 +0 -0
  20. {docwright-0.1.4 → docwright-0.1.6}/docwright/built_in_templates/wiki/data-model.md.j2 +0 -0
  21. {docwright-0.1.4 → docwright-0.1.6}/docwright/built_in_templates/wiki/db-schema.md.j2 +0 -0
  22. {docwright-0.1.4 → docwright-0.1.6}/docwright/built_in_templates/wiki/development-guide.md.j2 +0 -0
  23. {docwright-0.1.4 → docwright-0.1.6}/docwright/built_in_templates/wiki/home.md.j2 +0 -0
  24. {docwright-0.1.4 → docwright-0.1.6}/docwright/built_in_templates/wiki/integrations.md.j2 +0 -0
  25. {docwright-0.1.4 → docwright-0.1.6}/docwright/built_in_templates/wiki/operations.md.j2 +0 -0
  26. {docwright-0.1.4 → docwright-0.1.6}/docwright/built_in_templates/wiki/security.md.j2 +0 -0
  27. {docwright-0.1.4 → docwright-0.1.6}/docwright/built_in_templates/wiki/troubleshooting.md.j2 +0 -0
  28. {docwright-0.1.4 → docwright-0.1.6}/docwright/outputs/__init__.py +0 -0
  29. {docwright-0.1.4 → docwright-0.1.6}/docwright/outputs/base.py +0 -0
  30. {docwright-0.1.4 → docwright-0.1.6}/docwright/outputs/direct.py +0 -0
  31. {docwright-0.1.4 → docwright-0.1.6}/docwright/outputs/pull_request.py +0 -0
  32. {docwright-0.1.4 → docwright-0.1.6}/docwright/providers/__init__.py +0 -0
  33. {docwright-0.1.4 → docwright-0.1.6}/docwright/providers/base.py +0 -0
  34. {docwright-0.1.4 → docwright-0.1.6}/docwright/providers/claude.py +0 -0
  35. {docwright-0.1.4 → docwright-0.1.6}/docwright/providers/factory.py +0 -0
  36. {docwright-0.1.4 → docwright-0.1.6}/docwright/providers/ollama.py +0 -0
  37. {docwright-0.1.4 → docwright-0.1.6}/docwright/providers/openai.py +0 -0
  38. {docwright-0.1.4 → docwright-0.1.6}/docwright/registry.py +0 -0
  39. {docwright-0.1.4 → docwright-0.1.6}/docwright/renderer.py +0 -0
  40. {docwright-0.1.4 → docwright-0.1.6}/docwright/reporters/__init__.py +0 -0
  41. {docwright-0.1.4 → docwright-0.1.6}/docwright/reporters/html.py +0 -0
  42. {docwright-0.1.4 → docwright-0.1.6}/docwright/reporters/terminal.py +0 -0
  43. {docwright-0.1.4 → docwright-0.1.6}/docwright/scaffolder.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: docwright
3
- Version: 0.1.4
3
+ Version: 0.1.6
4
4
  Summary: AI-powered documentation agent: auto-generates and maintains README & wiki on every commit
5
5
  License: MIT
6
6
  License-File: LICENSE
@@ -29,10 +29,96 @@ def cli() -> None:
29
29
  """AI-powered documentation agent."""
30
30
 
31
31
 
32
+ def run_interactive_setup(repo_root: Path) -> None:
33
+ """Run interactive setup wizard and write .ai-docgen/ai-docgen.yml."""
34
+ provider = click.prompt(
35
+ "AI Provider",
36
+ type=click.Choice(["claude", "openai", "ollama"]),
37
+ default="openai",
38
+ show_choices=True,
39
+ )
40
+ model_defaults = {"claude": "claude-opus-4-5", "openai": "gpt-4o", "ollama": "llama3"}
41
+ model = click.prompt("Model", default=model_defaults.get(provider, "gpt-4o"))
42
+ api_key_env_defaults = {
43
+ "claude": "ANTHROPIC_API_KEY",
44
+ "openai": "OPENAI_API_KEY",
45
+ "ollama": "",
46
+ }
47
+ api_key_env = click.prompt(
48
+ "API key environment variable",
49
+ default=api_key_env_defaults.get(provider, "OPENAI_API_KEY"),
50
+ )
51
+ language = click.prompt(
52
+ "Language",
53
+ type=click.Choice(["en", "ru"]),
54
+ default="en",
55
+ show_choices=True,
56
+ )
57
+ output_mode = click.prompt(
58
+ "Output mode",
59
+ type=click.Choice(["direct", "pull_request", "gitlab_wiki"]),
60
+ default="direct",
61
+ show_choices=True,
62
+ )
63
+
64
+ wiki_url: str | None = None
65
+ token_env: str | None = None
66
+ if output_mode == "gitlab_wiki":
67
+ wiki_url = click.prompt("GitLab Wiki URL")
68
+ token_env = click.prompt("GitLab token env variable", default="CI_JOB_TOKEN")
69
+
70
+ config_dir = repo_root / ".ai-docgen"
71
+ config_dir.mkdir(parents=True, exist_ok=True)
72
+ config_path = config_dir / "ai-docgen.yml"
73
+
74
+ output_section: dict[str, object] = {"mode": output_mode}
75
+ if wiki_url:
76
+ output_section["wiki_url"] = wiki_url
77
+ if token_env:
78
+ output_section["token_env"] = token_env
79
+
80
+ config_data: dict[str, object] = {
81
+ "provider": {
82
+ "type": provider,
83
+ "model": model,
84
+ "api_key_env": api_key_env,
85
+ },
86
+ "output": output_section,
87
+ "language": language,
88
+ }
89
+
90
+ import yaml
91
+
92
+ config_path.write_text(yaml.dump(config_data, default_flow_style=False, allow_unicode=True))
93
+
94
+ click.echo(f"\n✓ Config saved to {config_path.relative_to(repo_root)}\n")
95
+ click.echo("Set these environment variables before running:")
96
+ if api_key_env:
97
+ click.echo(f" export {api_key_env}=... # AI provider key")
98
+ if output_mode == "gitlab_wiki" and token_env:
99
+ click.echo(f" export {token_env}=... # GitLab token (if gitlab_wiki mode)")
100
+ click.echo("\nIn GitLab CI — add them to:")
101
+ click.echo(" Group → Settings → CI/CD → Variables")
102
+ click.echo(" (CI_JOB_TOKEN is provided automatically for GitLab token)")
103
+ else:
104
+ click.echo(
105
+ f"\n export {api_key_env or 'OPENAI_API_KEY'}=... # platform.openai.com → API Keys"
106
+ )
107
+ click.echo("\nIn GitLab CI — add to Group → Settings → CI/CD → Variables")
108
+
109
+ click.echo("\nProceeding with initialization...")
110
+
111
+
32
112
  @cli.command()
33
113
  def init() -> None:
34
114
  """Generate documentation from scratch."""
35
- engine = build_engine(get_repo_root())
115
+ repo_root = get_repo_root()
116
+ from docwright.config import CONFIG_DIR, CONFIG_FILE
117
+
118
+ config_exists = (repo_root / CONFIG_DIR / CONFIG_FILE).exists()
119
+ if not config_exists:
120
+ run_interactive_setup(repo_root)
121
+ engine = build_engine(repo_root)
36
122
  asyncio.run(engine.init())
37
123
  click.echo("Documentation initialized.")
38
124
 
@@ -19,9 +19,11 @@ class ProviderConfig(BaseModel):
19
19
 
20
20
 
21
21
  class OutputConfig(BaseModel):
22
- mode: Literal["direct", "pr"] = "pr"
22
+ mode: str = "direct"
23
23
  pr_title: str = "docs: auto-update documentation"
24
24
  branch_prefix: str = "docs/auto-"
25
+ wiki_url: str | None = None
26
+ token_env: str | None = None
25
27
 
26
28
 
27
29
  class TemplatesConfig(BaseModel):
@@ -72,7 +72,7 @@ class DocsEngine:
72
72
  for doc_config in self.config.documents:
73
73
  target = self.repo_root / doc_config.target
74
74
  template_text = self.loader.load(doc_config.template)
75
- document = target.read_text() if target.exists() else template_text
75
+ document = template_text
76
76
  section_names = self.renderer.auto_section_names(template_text)
77
77
 
78
78
  for section_name in section_names:
@@ -0,0 +1,24 @@
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ from pathlib import Path
5
+
6
+ from docwright.config import OutputConfig
7
+ from docwright.outputs.base import Output
8
+ from docwright.outputs.direct import DirectOutput
9
+ from docwright.outputs.pull_request import PullRequestOutput
10
+
11
+
12
+ def build_output(config: OutputConfig, repo_root: Path) -> Output:
13
+ if config.mode == "direct":
14
+ return DirectOutput(repo_root=repo_root)
15
+ elif config.mode == "gitlab_wiki":
16
+ token = os.getenv(config.token_env or "CI_JOB_TOKEN", "")
17
+ if not token:
18
+ raise OSError("GitLab token not found. Set CI_JOB_TOKEN or configure token_env.")
19
+ if not config.wiki_url:
20
+ raise ValueError("output.wiki_url is required for gitlab_wiki mode.")
21
+ from docwright.outputs.gitlab_wiki import GitLabWikiOutput
22
+
23
+ return GitLabWikiOutput(wiki_url=config.wiki_url, token=token, repo_root=repo_root)
24
+ return PullRequestOutput(repo_root=repo_root, config=config)
@@ -0,0 +1,36 @@
1
+ from __future__ import annotations
2
+
3
+ import shutil
4
+ import tempfile
5
+ from pathlib import Path
6
+ from urllib.parse import urlparse, urlunparse
7
+
8
+ from git import Repo
9
+
10
+ from docwright.outputs.base import Output
11
+
12
+
13
+ class GitLabWikiOutput(Output):
14
+ def __init__(self, wiki_url: str, token: str, repo_root: Path) -> None:
15
+ self.wiki_url = wiki_url
16
+ self.token = token
17
+ self.repo_root = repo_root
18
+
19
+ def build_auth_url(self) -> str:
20
+ parsed = urlparse(self.wiki_url)
21
+ auth_netloc = f"oauth2:{self.token}@{parsed.netloc}"
22
+ return urlunparse(parsed._replace(netloc=auth_netloc))
23
+
24
+ def apply(self, changed_files: list[Path], message: str) -> None:
25
+ auth_url = self.build_auth_url()
26
+ tmp_dir = tempfile.mkdtemp()
27
+ try:
28
+ repo = Repo.clone_from(auth_url, tmp_dir)
29
+ for file in changed_files:
30
+ dest = Path(tmp_dir) / file.name
31
+ dest.write_bytes(file.read_bytes())
32
+ repo.index.add("*")
33
+ repo.index.commit(message)
34
+ repo.remotes.origin.push()
35
+ finally:
36
+ shutil.rmtree(tmp_dir, ignore_errors=True)
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "docwright"
3
- version = "0.1.4"
3
+ version = "0.1.6"
4
4
  description = "AI-powered documentation agent: auto-generates and maintains README & wiki on every commit"
5
5
  authors = ["Artem Gotlib <gotlib.artem.m@gmail.com>"]
6
6
  license = "MIT"
@@ -1,12 +0,0 @@
1
- from pathlib import Path
2
-
3
- from docwright.config import OutputConfig
4
- from docwright.outputs.base import Output
5
- from docwright.outputs.direct import DirectOutput
6
- from docwright.outputs.pull_request import PullRequestOutput
7
-
8
-
9
- def build_output(config: OutputConfig, repo_root: Path) -> Output:
10
- if config.mode == "direct":
11
- return DirectOutput(repo_root=repo_root)
12
- return PullRequestOutput(repo_root=repo_root, config=config)
File without changes
File without changes