py-openwiki 0.1.0__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.
- py_openwiki-0.1.0/.claude/settings.local.json +7 -0
- py_openwiki-0.1.0/.gitignore +32 -0
- py_openwiki-0.1.0/LICENSE +21 -0
- py_openwiki-0.1.0/PKG-INFO +158 -0
- py_openwiki-0.1.0/README.md +109 -0
- py_openwiki-0.1.0/pyproject.toml +81 -0
- py_openwiki-0.1.0/skills/migrate-wiki-to-okf/SKILL.md +44 -0
- py_openwiki-0.1.0/skills/write-connector/SKILL.md +45 -0
- py_openwiki-0.1.0/src/openwiki_py/__init__.py +1 -0
- py_openwiki-0.1.0/src/openwiki_py/__main__.py +4 -0
- py_openwiki-0.1.0/src/openwiki_py/agent/docs_only_backend.py +66 -0
- py_openwiki-0.1.0/src/openwiki_py/agent/frontmatter.py +295 -0
- py_openwiki-0.1.0/src/openwiki_py/agent/index_middleware.py +409 -0
- py_openwiki-0.1.0/src/openwiki_py/agent/prompt.py +471 -0
- py_openwiki-0.1.0/src/openwiki_py/agent/providers.py +69 -0
- py_openwiki-0.1.0/src/openwiki_py/agent/runtime.py +333 -0
- py_openwiki-0.1.0/src/openwiki_py/agent/skills.py +50 -0
- py_openwiki-0.1.0/src/openwiki_py/agent/stream_adapter.py +123 -0
- py_openwiki-0.1.0/src/openwiki_py/agent/types.py +63 -0
- py_openwiki-0.1.0/src/openwiki_py/agent/utils.py +351 -0
- py_openwiki-0.1.0/src/openwiki_py/auth/configure.py +167 -0
- py_openwiki-0.1.0/src/openwiki_py/auth/ngrok.py +184 -0
- py_openwiki-0.1.0/src/openwiki_py/auth/oauth.py +414 -0
- py_openwiki-0.1.0/src/openwiki_py/auth/providers.py +106 -0
- py_openwiki-0.1.0/src/openwiki_py/auth/tokens.py +136 -0
- py_openwiki-0.1.0/src/openwiki_py/cli.py +197 -0
- py_openwiki-0.1.0/src/openwiki_py/code_mode.py +143 -0
- py_openwiki-0.1.0/src/openwiki_py/commands.py +579 -0
- py_openwiki-0.1.0/src/openwiki_py/connectors/io.py +89 -0
- py_openwiki-0.1.0/src/openwiki_py/connectors/mcp_client.py +450 -0
- py_openwiki-0.1.0/src/openwiki_py/connectors/mcp_runtime.py +213 -0
- py_openwiki-0.1.0/src/openwiki_py/connectors/registry.py +63 -0
- py_openwiki-0.1.0/src/openwiki_py/connectors/sources/git_repo.py +140 -0
- py_openwiki-0.1.0/src/openwiki_py/connectors/sources/google.py +283 -0
- py_openwiki-0.1.0/src/openwiki_py/connectors/sources/hackernews.py +183 -0
- py_openwiki-0.1.0/src/openwiki_py/connectors/sources/mcp.py +164 -0
- py_openwiki-0.1.0/src/openwiki_py/connectors/sources/slack.py +421 -0
- py_openwiki-0.1.0/src/openwiki_py/connectors/sources/web_search.py +192 -0
- py_openwiki-0.1.0/src/openwiki_py/connectors/sources/x.py +289 -0
- py_openwiki-0.1.0/src/openwiki_py/connectors/tools.py +223 -0
- py_openwiki-0.1.0/src/openwiki_py/constants.py +441 -0
- py_openwiki-0.1.0/src/openwiki_py/credentials.py +136 -0
- py_openwiki-0.1.0/src/openwiki_py/data/skills/migrate-wiki-to-okf/SKILL.md +44 -0
- py_openwiki-0.1.0/src/openwiki_py/data/skills/write-connector/SKILL.md +45 -0
- py_openwiki-0.1.0/src/openwiki_py/diagnostics.py +112 -0
- py_openwiki-0.1.0/src/openwiki_py/env.py +410 -0
- py_openwiki-0.1.0/src/openwiki_py/fs_errors.py +11 -0
- py_openwiki-0.1.0/src/openwiki_py/ingestion.py +366 -0
- py_openwiki-0.1.0/src/openwiki_py/onboarding.py +282 -0
- py_openwiki-0.1.0/src/openwiki_py/openwiki_home.py +72 -0
- py_openwiki-0.1.0/src/openwiki_py/schedules.py +228 -0
- py_openwiki-0.1.0/src/openwiki_py/startup.py +67 -0
- py_openwiki-0.1.0/src/openwiki_py/telemetry/__init__.py +23 -0
- py_openwiki-0.1.0/src/openwiki_py/telemetry/client.py +35 -0
- py_openwiki-0.1.0/src/openwiki_py/telemetry/config.py +23 -0
- py_openwiki-0.1.0/src/openwiki_py/telemetry/errors.py +47 -0
- py_openwiki-0.1.0/src/openwiki_py/telemetry/gates.py +48 -0
- py_openwiki-0.1.0/src/openwiki_py/telemetry/install_id.py +42 -0
- py_openwiki-0.1.0/src/openwiki_py/telemetry/record_run_safe.py +28 -0
- py_openwiki-0.1.0/src/openwiki_py/telemetry/senders.py +101 -0
- py_openwiki-0.1.0/src/openwiki_py/tui/app.py +427 -0
- py_openwiki-0.1.0/src/openwiki_py/tui/chat.py +33 -0
- py_openwiki-0.1.0/src/openwiki_py/tui/menus.py +46 -0
- py_openwiki-0.1.0/src/openwiki_py/tui/onboarding/ingestion.py +226 -0
- py_openwiki-0.1.0/src/openwiki_py/tui/onboarding/oauth.py +121 -0
- py_openwiki-0.1.0/src/openwiki_py/tui/onboarding/screens.py +331 -0
- py_openwiki-0.1.0/src/openwiki_py/tui/print_mode.py +62 -0
- py_openwiki-0.1.0/src/openwiki_py/tui/run_log.py +16 -0
- py_openwiki-0.1.0/src/openwiki_py/tui/slash.py +31 -0
- py_openwiki-0.1.0/src/openwiki_py/tui/widgets.py +34 -0
- py_openwiki-0.1.0/src/openwiki_py/tui/workers.py +11 -0
- py_openwiki-0.1.0/tests/conftest.py +42 -0
- py_openwiki-0.1.0/tests/test_agent_utils.py +196 -0
- py_openwiki-0.1.0/tests/test_cli.py +49 -0
- py_openwiki-0.1.0/tests/test_code_mode.py +99 -0
- py_openwiki-0.1.0/tests/test_commands.py +300 -0
- py_openwiki-0.1.0/tests/test_configure.py +97 -0
- py_openwiki-0.1.0/tests/test_connectors.py +36 -0
- py_openwiki-0.1.0/tests/test_constants.py +204 -0
- py_openwiki-0.1.0/tests/test_credentials.py +26 -0
- py_openwiki-0.1.0/tests/test_docs_only_backend.py +89 -0
- py_openwiki-0.1.0/tests/test_env.py +79 -0
- py_openwiki-0.1.0/tests/test_frontmatter_validator.py +132 -0
- py_openwiki-0.1.0/tests/test_git_repo.py +85 -0
- py_openwiki-0.1.0/tests/test_google.py +96 -0
- py_openwiki-0.1.0/tests/test_hackernews.py +104 -0
- py_openwiki-0.1.0/tests/test_index_middleware.py +220 -0
- py_openwiki-0.1.0/tests/test_ingestion.py +109 -0
- py_openwiki-0.1.0/tests/test_mcp.py +239 -0
- py_openwiki-0.1.0/tests/test_ngrok.py +65 -0
- py_openwiki-0.1.0/tests/test_oauth.py +90 -0
- py_openwiki-0.1.0/tests/test_prompt.py +24 -0
- py_openwiki-0.1.0/tests/test_prompt_okf.py +11 -0
- py_openwiki-0.1.0/tests/test_providers.py +44 -0
- py_openwiki-0.1.0/tests/test_runtime.py +76 -0
- py_openwiki-0.1.0/tests/test_schedules.py +79 -0
- py_openwiki-0.1.0/tests/test_skills.py +52 -0
- py_openwiki-0.1.0/tests/test_slack.py +106 -0
- py_openwiki-0.1.0/tests/test_startup.py +139 -0
- py_openwiki-0.1.0/tests/test_stream_adapter.py +125 -0
- py_openwiki-0.1.0/tests/test_telemetry.py +101 -0
- py_openwiki-0.1.0/tests/test_tui.py +159 -0
- py_openwiki-0.1.0/tests/test_version.py +4 -0
- py_openwiki-0.1.0/tests/test_web_search.py +111 -0
- py_openwiki-0.1.0/tests/test_x.py +129 -0
- py_openwiki-0.1.0/uv.lock +3042 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
build/
|
|
8
|
+
dist/
|
|
9
|
+
*.egg-info/
|
|
10
|
+
.eggs/
|
|
11
|
+
|
|
12
|
+
# Virtual environments
|
|
13
|
+
.venv/
|
|
14
|
+
venv/
|
|
15
|
+
env/
|
|
16
|
+
|
|
17
|
+
# Tooling caches
|
|
18
|
+
.mypy_cache/
|
|
19
|
+
.ruff_cache/
|
|
20
|
+
.pytest_cache/
|
|
21
|
+
.cache/
|
|
22
|
+
.coverage
|
|
23
|
+
htmlcov/
|
|
24
|
+
|
|
25
|
+
# Environment / secrets
|
|
26
|
+
.env
|
|
27
|
+
.env.*
|
|
28
|
+
|
|
29
|
+
# Editors / OS
|
|
30
|
+
.vscode/
|
|
31
|
+
.idea/
|
|
32
|
+
.DS_Store
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: py-openwiki
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python port of OpenWiki — DeepAgents documentation CLI
|
|
5
|
+
License: MIT
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Classifier: Development Status :: 3 - Alpha
|
|
8
|
+
Classifier: Environment :: Console
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Topic :: Documentation
|
|
17
|
+
Classifier: Topic :: Software Development :: Documentation
|
|
18
|
+
Classifier: Topic :: Text Processing :: Markup
|
|
19
|
+
Classifier: Typing :: Typed
|
|
20
|
+
Requires-Python: >=3.11
|
|
21
|
+
Requires-Dist: cron-descriptor>=1.4
|
|
22
|
+
Requires-Dist: croniter>=2.0
|
|
23
|
+
Requires-Dist: deepagents>=0.6.12
|
|
24
|
+
Requires-Dist: google-auth>=2.0
|
|
25
|
+
Requires-Dist: httpx>=0.28
|
|
26
|
+
Requires-Dist: langchain-anthropic>=1.4.7
|
|
27
|
+
Requires-Dist: langchain-aws>=1.6.0
|
|
28
|
+
Requires-Dist: langchain-core>=1.4.8
|
|
29
|
+
Requires-Dist: langchain-google-genai>=4.2.5
|
|
30
|
+
Requires-Dist: langchain-openai>=0.3
|
|
31
|
+
Requires-Dist: langchain-tavily>=0.2
|
|
32
|
+
Requires-Dist: langchain>=1.3.11
|
|
33
|
+
Requires-Dist: langgraph-checkpoint-sqlite>=2.0
|
|
34
|
+
Requires-Dist: langgraph>=0.4
|
|
35
|
+
Requires-Dist: posthog>=3.0
|
|
36
|
+
Requires-Dist: pyyaml>=6.0
|
|
37
|
+
Requires-Dist: rich>=13.9
|
|
38
|
+
Requires-Dist: textual>=1.0
|
|
39
|
+
Requires-Dist: typer>=0.15
|
|
40
|
+
Provides-Extra: aws
|
|
41
|
+
Requires-Dist: deepagents[aws]; extra == 'aws'
|
|
42
|
+
Provides-Extra: dev
|
|
43
|
+
Requires-Dist: mypy>=1.14; extra == 'dev'
|
|
44
|
+
Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
|
|
45
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
46
|
+
Requires-Dist: ruff>=0.9; extra == 'dev'
|
|
47
|
+
Requires-Dist: types-pyyaml; extra == 'dev'
|
|
48
|
+
Description-Content-Type: text/markdown
|
|
49
|
+
|
|
50
|
+
# OpenWiki (Python)
|
|
51
|
+
|
|
52
|
+
`openwiki-py` is a [DeepAgents](https://github.com/langchain-ai/deepagents)-based
|
|
53
|
+
CLI, built on LangChain/LangGraph, that writes and maintains agent wikis for
|
|
54
|
+
codebases or personal knowledge.
|
|
55
|
+
|
|
56
|
+
`openwiki-py` has two modes:
|
|
57
|
+
|
|
58
|
+
- **Code mode** builds repository documentation under `openwiki/` for the
|
|
59
|
+
current codebase.
|
|
60
|
+
- **Personal mode** builds a local personal brain wiki in `~/.openwiki/wiki`
|
|
61
|
+
from configured sources (local git repos, Gmail, web search, Hacker News,
|
|
62
|
+
Slack, X/Twitter).
|
|
63
|
+
|
|
64
|
+
Wiki output follows the [Open Knowledge Format (OKF) v0.1](https://github.com/GoogleCloudPlatform/knowledge-catalog/blob/main/okf/SPEC.md):
|
|
65
|
+
Markdown concepts carry YAML front matter with a `type`, `index.md`/`log.md`
|
|
66
|
+
are reserved documents rather than concepts, and standard Markdown links
|
|
67
|
+
express relationships between concept documents.
|
|
68
|
+
|
|
69
|
+
## Installation
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
uv sync --all-extras
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## CLI usage
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
uv run openwiki-py --help
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
openwiki-py [--init|--update] [message]
|
|
83
|
+
openwiki-py code [--init|--update] [message]
|
|
84
|
+
openwiki-py personal [--init|--update] [message]
|
|
85
|
+
openwiki-py --mode <personal|code> [--init|--update] [message]
|
|
86
|
+
openwiki-py auth <provider>
|
|
87
|
+
openwiki-py auth configure <provider> [--force]
|
|
88
|
+
openwiki-py auth tools <provider>
|
|
89
|
+
openwiki-py ingest <source|source-instance|all>
|
|
90
|
+
openwiki-py cron list|pause|resume|delete <source|all>
|
|
91
|
+
openwiki-py ngrok start [url] [--port <port>]
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Bare `openwiki-py` opens the interactive code-mode chat for the current
|
|
95
|
+
repository. Use `-p`/`--print` for a one-shot, non-interactive run. See
|
|
96
|
+
`openwiki-py --help` for the full command and option reference.
|
|
97
|
+
|
|
98
|
+
On the first interactive run, `openwiki-py` walks you through configuring an
|
|
99
|
+
inference provider, API key, and model, plus optional connector setup.
|
|
100
|
+
Configuration and secrets are saved to `~/.openwiki/.env`.
|
|
101
|
+
|
|
102
|
+
## Providers
|
|
103
|
+
|
|
104
|
+
Supported inference providers include OpenAI, OpenRouter, Gemini (AI Studio),
|
|
105
|
+
Gemini Enterprise (Vertex AI), Nebius Token Factory, Fireworks, Baseten,
|
|
106
|
+
NVIDIA NIM, an OpenAI-compatible endpoint, AWS Bedrock, and Anthropic. Set
|
|
107
|
+
`OPENWIKI_PROVIDER` and the matching credentials (for example
|
|
108
|
+
`ANTHROPIC_API_KEY`, `GEMINI_API_KEY`, or the Bedrock
|
|
109
|
+
`BEDROCK_AWS_*`/`OPENWIKI_MODEL_ID` triple) in your environment or
|
|
110
|
+
`~/.openwiki/.env`.
|
|
111
|
+
|
|
112
|
+
## Connectors
|
|
113
|
+
|
|
114
|
+
Built-in ingestion connectors: `git-repo`, `google` (Gmail), `x`
|
|
115
|
+
(X/Twitter), `web-search` (Tavily), `hackernews`, and Slack. Deterministic
|
|
116
|
+
connector tools write raw data under `~/.openwiki/connectors/<connector>/raw/`,
|
|
117
|
+
then source-specific agent runs synthesize the personal wiki from those
|
|
118
|
+
files. Authenticate a provider with `openwiki-py auth <provider>`; connector
|
|
119
|
+
secrets are referenced by env var name and stored in `~/.openwiki/.env`.
|
|
120
|
+
|
|
121
|
+
## Telemetry
|
|
122
|
+
|
|
123
|
+
`openwiki-py` collects anonymous, aggregate usage telemetry (command, outcome,
|
|
124
|
+
and coarse error category on init/update runs) keyed by a random install ID —
|
|
125
|
+
never file contents, credentials, prompts, model output, or connector
|
|
126
|
+
payloads. Disable it with `OPENWIKI_TELEMETRY_DISABLED=1` or `DO_NOT_TRACK=1`.
|
|
127
|
+
|
|
128
|
+
## Development
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
uv sync --all-extras # install package + dev dependencies
|
|
132
|
+
uv run pytest # run the test suite
|
|
133
|
+
uv run ruff check . # lint
|
|
134
|
+
uv run mypy . # type-check
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Source lives under [src/openwiki_py/](src/openwiki_py/):
|
|
138
|
+
|
|
139
|
+
- `agent/` — DeepAgents runtime, prompts, provider wiring, and skills loading.
|
|
140
|
+
- `auth/` — OAuth flows, token storage, and per-provider connector configuration.
|
|
141
|
+
- `connectors/` — built-in ingestion sources (git repo, Google/Gmail, Slack, X,
|
|
142
|
+
web search, Hacker News) plus the connector registry and MCP client/runtime.
|
|
143
|
+
- `telemetry/` — anonymous, opt-out usage telemetry.
|
|
144
|
+
- `tui/` — the Textual-based interactive chat app and print-mode runner.
|
|
145
|
+
- `cli.py`, `commands.py`, `startup.py` — argument parsing and command dispatch.
|
|
146
|
+
|
|
147
|
+
Repository-local [skills/](skills/) (also installed under
|
|
148
|
+
`src/openwiki_py/data/skills/`) define agent workflows such as
|
|
149
|
+
[migrate-wiki-to-okf](skills/migrate-wiki-to-okf/SKILL.md) and
|
|
150
|
+
[write-connector](skills/write-connector/SKILL.md).
|
|
151
|
+
|
|
152
|
+
Tests live in [tests/](tests/) and mirror the `src/openwiki_py` layout.
|
|
153
|
+
|
|
154
|
+
## Configuration
|
|
155
|
+
|
|
156
|
+
Config, credentials, connector state, and the generated personal wiki are
|
|
157
|
+
stored under `~/.openwiki/` (`~/.openwiki/.env`, `~/.openwiki/wiki/`,
|
|
158
|
+
`~/.openwiki/connectors/`).
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# OpenWiki (Python)
|
|
2
|
+
|
|
3
|
+
`openwiki-py` is a [DeepAgents](https://github.com/langchain-ai/deepagents)-based
|
|
4
|
+
CLI, built on LangChain/LangGraph, that writes and maintains agent wikis for
|
|
5
|
+
codebases or personal knowledge.
|
|
6
|
+
|
|
7
|
+
`openwiki-py` has two modes:
|
|
8
|
+
|
|
9
|
+
- **Code mode** builds repository documentation under `openwiki/` for the
|
|
10
|
+
current codebase.
|
|
11
|
+
- **Personal mode** builds a local personal brain wiki in `~/.openwiki/wiki`
|
|
12
|
+
from configured sources (local git repos, Gmail, web search, Hacker News,
|
|
13
|
+
Slack, X/Twitter).
|
|
14
|
+
|
|
15
|
+
Wiki output follows the [Open Knowledge Format (OKF) v0.1](https://github.com/GoogleCloudPlatform/knowledge-catalog/blob/main/okf/SPEC.md):
|
|
16
|
+
Markdown concepts carry YAML front matter with a `type`, `index.md`/`log.md`
|
|
17
|
+
are reserved documents rather than concepts, and standard Markdown links
|
|
18
|
+
express relationships between concept documents.
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
uv sync --all-extras
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## CLI usage
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
uv run openwiki-py --help
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
openwiki-py [--init|--update] [message]
|
|
34
|
+
openwiki-py code [--init|--update] [message]
|
|
35
|
+
openwiki-py personal [--init|--update] [message]
|
|
36
|
+
openwiki-py --mode <personal|code> [--init|--update] [message]
|
|
37
|
+
openwiki-py auth <provider>
|
|
38
|
+
openwiki-py auth configure <provider> [--force]
|
|
39
|
+
openwiki-py auth tools <provider>
|
|
40
|
+
openwiki-py ingest <source|source-instance|all>
|
|
41
|
+
openwiki-py cron list|pause|resume|delete <source|all>
|
|
42
|
+
openwiki-py ngrok start [url] [--port <port>]
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Bare `openwiki-py` opens the interactive code-mode chat for the current
|
|
46
|
+
repository. Use `-p`/`--print` for a one-shot, non-interactive run. See
|
|
47
|
+
`openwiki-py --help` for the full command and option reference.
|
|
48
|
+
|
|
49
|
+
On the first interactive run, `openwiki-py` walks you through configuring an
|
|
50
|
+
inference provider, API key, and model, plus optional connector setup.
|
|
51
|
+
Configuration and secrets are saved to `~/.openwiki/.env`.
|
|
52
|
+
|
|
53
|
+
## Providers
|
|
54
|
+
|
|
55
|
+
Supported inference providers include OpenAI, OpenRouter, Gemini (AI Studio),
|
|
56
|
+
Gemini Enterprise (Vertex AI), Nebius Token Factory, Fireworks, Baseten,
|
|
57
|
+
NVIDIA NIM, an OpenAI-compatible endpoint, AWS Bedrock, and Anthropic. Set
|
|
58
|
+
`OPENWIKI_PROVIDER` and the matching credentials (for example
|
|
59
|
+
`ANTHROPIC_API_KEY`, `GEMINI_API_KEY`, or the Bedrock
|
|
60
|
+
`BEDROCK_AWS_*`/`OPENWIKI_MODEL_ID` triple) in your environment or
|
|
61
|
+
`~/.openwiki/.env`.
|
|
62
|
+
|
|
63
|
+
## Connectors
|
|
64
|
+
|
|
65
|
+
Built-in ingestion connectors: `git-repo`, `google` (Gmail), `x`
|
|
66
|
+
(X/Twitter), `web-search` (Tavily), `hackernews`, and Slack. Deterministic
|
|
67
|
+
connector tools write raw data under `~/.openwiki/connectors/<connector>/raw/`,
|
|
68
|
+
then source-specific agent runs synthesize the personal wiki from those
|
|
69
|
+
files. Authenticate a provider with `openwiki-py auth <provider>`; connector
|
|
70
|
+
secrets are referenced by env var name and stored in `~/.openwiki/.env`.
|
|
71
|
+
|
|
72
|
+
## Telemetry
|
|
73
|
+
|
|
74
|
+
`openwiki-py` collects anonymous, aggregate usage telemetry (command, outcome,
|
|
75
|
+
and coarse error category on init/update runs) keyed by a random install ID —
|
|
76
|
+
never file contents, credentials, prompts, model output, or connector
|
|
77
|
+
payloads. Disable it with `OPENWIKI_TELEMETRY_DISABLED=1` or `DO_NOT_TRACK=1`.
|
|
78
|
+
|
|
79
|
+
## Development
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
uv sync --all-extras # install package + dev dependencies
|
|
83
|
+
uv run pytest # run the test suite
|
|
84
|
+
uv run ruff check . # lint
|
|
85
|
+
uv run mypy . # type-check
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Source lives under [src/openwiki_py/](src/openwiki_py/):
|
|
89
|
+
|
|
90
|
+
- `agent/` — DeepAgents runtime, prompts, provider wiring, and skills loading.
|
|
91
|
+
- `auth/` — OAuth flows, token storage, and per-provider connector configuration.
|
|
92
|
+
- `connectors/` — built-in ingestion sources (git repo, Google/Gmail, Slack, X,
|
|
93
|
+
web search, Hacker News) plus the connector registry and MCP client/runtime.
|
|
94
|
+
- `telemetry/` — anonymous, opt-out usage telemetry.
|
|
95
|
+
- `tui/` — the Textual-based interactive chat app and print-mode runner.
|
|
96
|
+
- `cli.py`, `commands.py`, `startup.py` — argument parsing and command dispatch.
|
|
97
|
+
|
|
98
|
+
Repository-local [skills/](skills/) (also installed under
|
|
99
|
+
`src/openwiki_py/data/skills/`) define agent workflows such as
|
|
100
|
+
[migrate-wiki-to-okf](skills/migrate-wiki-to-okf/SKILL.md) and
|
|
101
|
+
[write-connector](skills/write-connector/SKILL.md).
|
|
102
|
+
|
|
103
|
+
Tests live in [tests/](tests/) and mirror the `src/openwiki_py` layout.
|
|
104
|
+
|
|
105
|
+
## Configuration
|
|
106
|
+
|
|
107
|
+
Config, credentials, connector state, and the generated personal wiki are
|
|
108
|
+
stored under `~/.openwiki/` (`~/.openwiki/.env`, `~/.openwiki/wiki/`,
|
|
109
|
+
`~/.openwiki/connectors/`).
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "py-openwiki"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Python port of OpenWiki — DeepAgents documentation CLI"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.11"
|
|
7
|
+
license = { text = "MIT" }
|
|
8
|
+
classifiers = [
|
|
9
|
+
"Development Status :: 3 - Alpha",
|
|
10
|
+
"Environment :: Console",
|
|
11
|
+
"Intended Audience :: Developers",
|
|
12
|
+
"License :: OSI Approved :: MIT License",
|
|
13
|
+
"Operating System :: OS Independent",
|
|
14
|
+
"Programming Language :: Python :: 3",
|
|
15
|
+
"Programming Language :: Python :: 3.11",
|
|
16
|
+
"Programming Language :: Python :: 3.12",
|
|
17
|
+
"Programming Language :: Python :: 3.13",
|
|
18
|
+
"Topic :: Documentation",
|
|
19
|
+
"Topic :: Software Development :: Documentation",
|
|
20
|
+
"Topic :: Text Processing :: Markup",
|
|
21
|
+
"Typing :: Typed",
|
|
22
|
+
]
|
|
23
|
+
dependencies = [
|
|
24
|
+
"deepagents>=0.6.12",
|
|
25
|
+
"langchain>=1.3.11",
|
|
26
|
+
"langchain-core>=1.4.8",
|
|
27
|
+
"langchain-openai>=0.3",
|
|
28
|
+
"langchain-anthropic>=1.4.7",
|
|
29
|
+
"langchain-google-genai>=4.2.5",
|
|
30
|
+
"langchain-aws>=1.6.0",
|
|
31
|
+
"langgraph>=0.4",
|
|
32
|
+
"langgraph-checkpoint-sqlite>=2.0",
|
|
33
|
+
"typer>=0.15",
|
|
34
|
+
"rich>=13.9",
|
|
35
|
+
"textual>=1.0",
|
|
36
|
+
"httpx>=0.28",
|
|
37
|
+
"pyyaml>=6.0",
|
|
38
|
+
"croniter>=2.0",
|
|
39
|
+
"cron-descriptor>=1.4",
|
|
40
|
+
"posthog>=3.0",
|
|
41
|
+
"google-auth>=2.0",
|
|
42
|
+
"langchain-tavily>=0.2",
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
[project.optional-dependencies]
|
|
46
|
+
aws = ["deepagents[aws]"]
|
|
47
|
+
dev = [
|
|
48
|
+
"pytest>=8.0",
|
|
49
|
+
"pytest-asyncio>=0.24",
|
|
50
|
+
"ruff>=0.9",
|
|
51
|
+
"mypy>=1.14",
|
|
52
|
+
"types-PyYAML",
|
|
53
|
+
]
|
|
54
|
+
|
|
55
|
+
[project.scripts]
|
|
56
|
+
openwiki-py = "openwiki_py.cli:main"
|
|
57
|
+
|
|
58
|
+
[build-system]
|
|
59
|
+
requires = ["hatchling"]
|
|
60
|
+
build-backend = "hatchling.build"
|
|
61
|
+
|
|
62
|
+
[tool.hatch.build.targets.wheel]
|
|
63
|
+
packages = ["src/openwiki_py"]
|
|
64
|
+
|
|
65
|
+
[tool.hatch.build.targets.wheel.sources]
|
|
66
|
+
"src" = ""
|
|
67
|
+
|
|
68
|
+
[tool.uv]
|
|
69
|
+
|
|
70
|
+
[tool.ruff]
|
|
71
|
+
line-length = 100
|
|
72
|
+
target-version = "py311"
|
|
73
|
+
|
|
74
|
+
[tool.mypy]
|
|
75
|
+
python_version = "3.12"
|
|
76
|
+
strict = false
|
|
77
|
+
packages = ["openwiki_py"]
|
|
78
|
+
|
|
79
|
+
[tool.pytest.ini_options]
|
|
80
|
+
asyncio_mode = "auto"
|
|
81
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: migrate-wiki-to-okf
|
|
3
|
+
description: Make an existing OpenWiki fully OKF-compliant. Use when any current wiki Markdown files lack valid OKF YAML front matter or when the user requests an OKF migration.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Migrate Wiki to OKF
|
|
7
|
+
|
|
8
|
+
Add or correct OKF front matter across the existing wiki without changing accurate document bodies.
|
|
9
|
+
|
|
10
|
+
## Workflow
|
|
11
|
+
|
|
12
|
+
1. Before editing, recursively inventory every directory under the wiki root. Include the root directory itself.
|
|
13
|
+
2. Write a plan listing every discovered directory and its assigned subagent.
|
|
14
|
+
3. Spawn exactly one subagent for each directory. If concurrency is limited, run them in batches; never combine multiple directories into one assignment.
|
|
15
|
+
4. Give each subagent write access only to Markdown files directly inside its assigned directory. It must not recurse into or modify another directory.
|
|
16
|
+
5. Wait for every subagent, then verify that every planned directory was processed. Send missed corrections back to a subagent scoped to that same directory.
|
|
17
|
+
|
|
18
|
+
## Subagent Task
|
|
19
|
+
|
|
20
|
+
Each subagent must:
|
|
21
|
+
|
|
22
|
+
- Inspect every non-reserved Markdown concept file directly in its assigned directory.
|
|
23
|
+
- Leave already compliant files unchanged.
|
|
24
|
+
- Add or correct only the leading YAML front matter when needed. Preserve the existing Markdown body.
|
|
25
|
+
- Preserve all valid existing front matter fields, including `timestamp` and producer-defined extension fields. Never delete an unknown field merely because OpenWiki did not create it.
|
|
26
|
+
- Require only a non-empty, descriptive `type`. Infer recommended `title` and one to two sentence `description` values when useful. Add `resource`, `tags`, or `timestamp` only when supported by the document and available evidence.
|
|
27
|
+
- Use this standard-field formatter while retaining any existing producer extensions:
|
|
28
|
+
|
|
29
|
+
```yaml
|
|
30
|
+
---
|
|
31
|
+
type: <Type name>
|
|
32
|
+
title: <Optional display name>
|
|
33
|
+
description: <Optional one to two sentence summary (optimized for search & retrieval)>
|
|
34
|
+
resource: <Optional canonical URI for the underlying asset>
|
|
35
|
+
tags: [<tag>, <tag>]
|
|
36
|
+
timestamp: <Optional ISO 8601 datetime>
|
|
37
|
+
---
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
- `index.md` and `log.md` are reserved OKF documents. Do not add concept front matter to them or process them as concepts; OpenWiki regenerates directory indexes deterministically after the run.
|
|
41
|
+
- Report the files checked, the files changed, and any file whose metadata could not be inferred confidently.
|
|
42
|
+
- The description field is important for retrieval tools. When present, make it clear, detailed, and optimized for search.
|
|
43
|
+
|
|
44
|
+
Do not create, delete, move, or reorganize wiki pages during this migration.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: write-connector
|
|
3
|
+
description: Add a new built-in OpenWiki source connector. Use when a user asks to create or implement an OpenWiki connector.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Write An OpenWiki Connector
|
|
7
|
+
|
|
8
|
+
OpenWiki connectors are built-in TypeScript modules in the OSS repository. Do not create a plugin marketplace, dynamic connector package, or runtime-loaded untrusted connector. Add normal source files and tests.
|
|
9
|
+
|
|
10
|
+
## Required Shape
|
|
11
|
+
|
|
12
|
+
- Add the connector to src/connectors/types.ts and src/connectors/registry.ts.
|
|
13
|
+
- Implement the connector under src/connectors/sources/<connector>.ts.
|
|
14
|
+
- The connector must expose a ConnectorRuntime with id, displayName, description, backend, requiredEnv, supportsAgenticDiscovery, and ingest().
|
|
15
|
+
- Ingestion writes raw JSON/manifests under ~/.openwiki/connectors/<id>/raw/<run-id>/.
|
|
16
|
+
- State lives in ~/.openwiki/connectors/<id>/state.json.
|
|
17
|
+
- Config lives in ~/.openwiki/connectors/<id>/config.json.
|
|
18
|
+
- Secrets live in ~/.openwiki/.env and are referenced only by env var name.
|
|
19
|
+
|
|
20
|
+
## Security Rules
|
|
21
|
+
|
|
22
|
+
- Never read, print, log, return, or hardcode secret values.
|
|
23
|
+
- Do not store credentials in connector config, raw files, state, logs, or tests.
|
|
24
|
+
- Validate connector IDs and raw file paths so reads and writes stay inside ~/.openwiki/connectors/<id>/.
|
|
25
|
+
- Use deterministic ingestion code for credentialed external fetching.
|
|
26
|
+
- If wrapping MCP, treat the MCP server as read-only and call only allowlisted read/dump operations from connector config.
|
|
27
|
+
- Do not let untrusted connector manifests instantiate arbitrary commands or arbitrary network endpoints without explicit built-in code review.
|
|
28
|
+
|
|
29
|
+
## Ingestion Rules
|
|
30
|
+
|
|
31
|
+
- Git/local repos should write compact manifests and let the agent inspect the local repo as the source of truth.
|
|
32
|
+
- Sources with timestamps should store per-stream cursors.
|
|
33
|
+
- Sources with object metadata should store IDs, last edited timestamps, and content hashes.
|
|
34
|
+
- Sources with pagination should store enough state to continue without refetching everything.
|
|
35
|
+
- Raw dumps should preserve source IDs, timestamps, URLs, authors, and enough provenance for citations.
|
|
36
|
+
|
|
37
|
+
## User-Facing Finish
|
|
38
|
+
|
|
39
|
+
When done, tell the user:
|
|
40
|
+
|
|
41
|
+
- which connector files changed,
|
|
42
|
+
- which env vars to set in ~/.openwiki/.env,
|
|
43
|
+
- what config file to create or edit,
|
|
44
|
+
- how to run openwiki personal --update to trigger ingestion,
|
|
45
|
+
- which scopes/permissions the source provider requires.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.0"
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
from typing import Any, Optional
|
|
2
|
+
from deepagents.backends import LocalShellBackend
|
|
3
|
+
from deepagents.backends.protocol import WriteResult, EditResult
|
|
4
|
+
from openwiki_py.constants import OPEN_WIKI_DIR
|
|
5
|
+
|
|
6
|
+
MUTATION_PATH_METADATA_KEY = "openwikiMutationPath"
|
|
7
|
+
|
|
8
|
+
class OpenWikiLocalShellBackend(LocalShellBackend):
|
|
9
|
+
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
|
10
|
+
docs_only = kwargs.pop("docsOnly", kwargs.pop("docs_only", False))
|
|
11
|
+
output_mode = kwargs.pop("outputMode", kwargs.pop("output_mode", "repository"))
|
|
12
|
+
|
|
13
|
+
# Map camelCase to snake_case for deepagents LocalShellBackend
|
|
14
|
+
if "rootDir" in kwargs:
|
|
15
|
+
kwargs["root_dir"] = kwargs.pop("rootDir")
|
|
16
|
+
if "virtualMode" in kwargs:
|
|
17
|
+
kwargs["virtual_mode"] = kwargs.pop("virtualMode")
|
|
18
|
+
|
|
19
|
+
super().__init__(*args, **kwargs)
|
|
20
|
+
self.docs_only = docs_only
|
|
21
|
+
self.output_mode = output_mode
|
|
22
|
+
|
|
23
|
+
def write(self, file_path: str, content: str) -> WriteResult:
|
|
24
|
+
error = self.get_docs_only_write_error(file_path)
|
|
25
|
+
if error:
|
|
26
|
+
return WriteResult(error=error)
|
|
27
|
+
return mark_mutation(super().write(file_path, content), file_path)
|
|
28
|
+
|
|
29
|
+
def edit(
|
|
30
|
+
self,
|
|
31
|
+
file_path: str,
|
|
32
|
+
old_string: str,
|
|
33
|
+
new_string: str,
|
|
34
|
+
replace_all: bool = False,
|
|
35
|
+
) -> EditResult:
|
|
36
|
+
error = self.get_docs_only_write_error(file_path)
|
|
37
|
+
if error:
|
|
38
|
+
return EditResult(error=error)
|
|
39
|
+
return mark_mutation(
|
|
40
|
+
super().edit(file_path, old_string, new_string, replace_all),
|
|
41
|
+
file_path,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
def get_docs_only_write_error(self, file_path: str) -> Optional[str]:
|
|
45
|
+
if (
|
|
46
|
+
not self.docs_only
|
|
47
|
+
or self.output_mode == "local-wiki"
|
|
48
|
+
or is_openwiki_docs_path(file_path)
|
|
49
|
+
):
|
|
50
|
+
return None
|
|
51
|
+
|
|
52
|
+
return f"OpenWiki repository init/update runs may only write under /{OPEN_WIKI_DIR}/. Refused path: {file_path}"
|
|
53
|
+
|
|
54
|
+
def mark_mutation(result: Any, file_path: str) -> Any:
|
|
55
|
+
if hasattr(result, "error") and not result.error:
|
|
56
|
+
if not hasattr(result, "metadata") or result.metadata is None:
|
|
57
|
+
result.metadata = {}
|
|
58
|
+
result.metadata[MUTATION_PATH_METADATA_KEY] = getattr(result, "path", None) or file_path
|
|
59
|
+
return result
|
|
60
|
+
|
|
61
|
+
def is_openwiki_docs_path(file_path: str) -> bool:
|
|
62
|
+
normalized = file_path.strip().replace("\\", "/")
|
|
63
|
+
virtual_path = normalized.lstrip("/")
|
|
64
|
+
return (
|
|
65
|
+
virtual_path == OPEN_WIKI_DIR or virtual_path.startswith(f"{OPEN_WIKI_DIR}/")
|
|
66
|
+
)
|