navdoc 0.2.4__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.
@@ -0,0 +1,7 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(uv run *)"
5
+ ]
6
+ }
7
+ }
@@ -0,0 +1 @@
1
+ NAVDOC_API_KEY=nd_...
@@ -0,0 +1,28 @@
1
+ # Environment
2
+ .env
3
+
4
+ # Lock file (library — consumers manage their own)
5
+ uv.lock
6
+
7
+ # Claude Code
8
+ CLAUDE.md
9
+
10
+ # Python
11
+ __pycache__/
12
+ *.py[cod]
13
+ *.egg-info/
14
+ dist/
15
+ build/
16
+ .venv/
17
+
18
+ # Testing
19
+ .pytest_cache/
20
+ .coverage
21
+ htmlcov/
22
+
23
+ # Type checking
24
+ .mypy_cache/
25
+
26
+ # Editor
27
+ .vscode/
28
+ .idea/
navdoc-0.2.4/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 pillyshi
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.
navdoc-0.2.4/PKG-INFO ADDED
@@ -0,0 +1,249 @@
1
+ Metadata-Version: 2.4
2
+ Name: navdoc
3
+ Version: 0.2.4
4
+ Summary: Python SDK for navdoc – RAG-powered chat with Claude via the navdoc REST API
5
+ Author: pillyshi
6
+ License: MIT
7
+ License-File: LICENSE
8
+ Keywords: anthropic,claude,llm,mcp,navdoc,rag
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Requires-Python: >=3.11
16
+ Requires-Dist: httpx>=0.28.0
17
+ Requires-Dist: prompt-toolkit>=3.0
18
+ Requires-Dist: typer>=0.12.0
19
+ Provides-Extra: dev
20
+ Requires-Dist: mypy>=1.13; extra == 'dev'
21
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
22
+ Requires-Dist: pytest-mock>=3.14; extra == 'dev'
23
+ Requires-Dist: pytest>=8.0; extra == 'dev'
24
+ Requires-Dist: ruff>=0.8; extra == 'dev'
25
+ Description-Content-Type: text/markdown
26
+
27
+ # navdoc-py
28
+
29
+ Python SDK and CLI for [navdoc](https://dashboard.navdoc.dev). Upload and manage your documents via the navdoc REST API, and run RAG-powered chat with Claude.
30
+
31
+ ## Installation
32
+
33
+ ```bash
34
+ pip install navdoc
35
+ ```
36
+
37
+ ## Credentials
38
+
39
+ ```bash
40
+ export NAVDOC_API_KEY=nd_...
41
+ ```
42
+
43
+ ## CLI
44
+
45
+ ### `navdoc ask`
46
+
47
+ Run a one-shot query.
48
+
49
+ ```bash
50
+ # Direct question
51
+ navdoc ask "What is asyncio?"
52
+ navdoc ask "What is asyncio?" --system-prompt "Be concise."
53
+
54
+ # Config-based
55
+ navdoc ask --config daily.json
56
+ navdoc ask --config daily.json --var date=2025-05-08
57
+ ```
58
+
59
+ Config format:
60
+
61
+ ```json
62
+ {
63
+ "name": "Daily Summary",
64
+ "description": "Summarize a day's lifelog entries with activity count and time-of-day trends",
65
+ "system_prompt": "You are a lifelog analyst. Respond in {{language}}.",
66
+ "user_prompt": "Please summarize the logs for {{date}}. Include the number of activities and time-of-day trends.",
67
+ "placeholders": [
68
+ {
69
+ "key": "date",
70
+ "label": "Target date",
71
+ "default": "today"
72
+ },
73
+ {
74
+ "key": "language",
75
+ "label": "Response language",
76
+ "default": "English"
77
+ }
78
+ ]
79
+ }
80
+ ```
81
+
82
+ - Both `system_prompt` and `user_prompt` support `{{key}}` placeholders.
83
+ - If `--var key=value` is not provided, missing placeholders are prompted interactively (unless a `default` is set).
84
+
85
+ ### `navdoc chat`
86
+
87
+ Start an interactive multi-turn chat session.
88
+
89
+ ```bash
90
+ # No config — plain chat
91
+ navdoc chat
92
+
93
+ # With a system prompt
94
+ navdoc chat --system-prompt "You are a helpful assistant."
95
+
96
+ # With a config file
97
+ navdoc chat --config qa.json
98
+ navdoc chat --config qa.json --var topic=asyncio
99
+ navdoc chat --config qa.json --no-initial-message
100
+ ```
101
+
102
+ `--config` is optional. If omitted, chat starts immediately with an empty (or `--system-prompt`-specified) prompt. If `user_prompt` is set in the config, it is sent as the first message automatically (`--no-initial-message` suppresses this). Type `exit` or press Ctrl+C to quit.
103
+
104
+ ## Python SDK
105
+
106
+ ### `NavdocClient`
107
+
108
+ ```python
109
+ from navdoc import NavdocClient
110
+
111
+ client = NavdocClient(
112
+ api_key="nd_...", # or NAVDOC_API_KEY env var
113
+ )
114
+ ```
115
+
116
+ ### Document management
117
+
118
+ Upload, list, and delete documents via the navdoc REST API.
119
+
120
+ #### `upload_document()`
121
+
122
+ ```python
123
+ from navdoc import NavdocClient, Document
124
+
125
+ doc = await client.upload_document(
126
+ "Full text content of the document...",
127
+ url="https://example.com/page", # unique identifier for the document
128
+ scope="my-scope", # optional
129
+ )
130
+ print(doc.document_id) # str
131
+ print(doc.chunk_count) # int
132
+ ```
133
+
134
+ #### `upload_chunks()`
135
+
136
+ Upload pre-split chunks instead of raw text (useful when you handle chunking yourself).
137
+
138
+ ```python
139
+ chunk_ids = await client.upload_chunks(
140
+ ["First chunk...", "Second chunk..."],
141
+ document_url="https://example.com/page",
142
+ scope="my-scope",
143
+ )
144
+ ```
145
+
146
+ #### `list_documents()`
147
+
148
+ ```python
149
+ docs = await client.list_documents(scope="my-scope", limit=50, offset=0)
150
+ for doc in docs:
151
+ print(doc.document_id, doc.chunk_count)
152
+ ```
153
+
154
+ #### `delete_document()`
155
+
156
+ ```python
157
+ await client.delete_document("doc_id_xxx")
158
+ ```
159
+
160
+ #### `Document` type
161
+
162
+ ```python
163
+ @dataclass
164
+ class Document:
165
+ document_id: str
166
+ chunk_count: int
167
+ ```
168
+
169
+ ### Scope management
170
+
171
+ Scopes are namespaces that group documents.
172
+
173
+ ```python
174
+ from navdoc import NavdocClient, Scope
175
+
176
+ scopes = await client.list_scopes()
177
+ scope = await client.create_scope("my-scope", visibility="private")
178
+ scope = await client.get_scope("my-scope")
179
+ scope = await client.update_scope("my-scope", visibility="public")
180
+ await client.delete_scope("my-scope") # also removes all documents inside
181
+ ```
182
+
183
+ #### `Scope` type
184
+
185
+ ```python
186
+ @dataclass
187
+ class Scope:
188
+ name: str
189
+ visibility: str # "private" | "public"
190
+ ```
191
+
192
+ ### Server-side agent
193
+
194
+ RAG chat powered by navdoc's built-in Claude agent.
195
+
196
+ #### `stream()` — streaming
197
+
198
+ Yields `StreamEvent` objects as the server sends them.
199
+
200
+ ```python
201
+ from navdoc import NavdocClient, StreamEvent
202
+
203
+ async for event in client.stream(
204
+ "What is asyncio?",
205
+ messages=[...], # optional conversation history
206
+ system_prompt="Answer concisely.",
207
+ timezone="Asia/Tokyo",
208
+ ):
209
+ if event.type == "text":
210
+ print(event.delta, end="", flush=True)
211
+ ```
212
+
213
+ #### `ask_server()` — non-streaming
214
+
215
+ Collects the full response and returns an `AgentResponse`.
216
+
217
+ ```python
218
+ response = await client.ask_server(
219
+ "What is asyncio?",
220
+ messages=[{"role": "user", "content": "previous turn"}, ...], # optional history
221
+ system_prompt="Answer concisely.",
222
+ timezone="Asia/Tokyo",
223
+ )
224
+ print(response.answer)
225
+ print(response.tool_calls)
226
+ ```
227
+
228
+ #### `StreamEvent` type
229
+
230
+ ```python
231
+ @dataclass
232
+ class StreamEvent:
233
+ type: str # "text" | "tool_use" | "tool_result" | "done" | "error"
234
+ delta: str | None = None # type=text
235
+ name: str | None = None # type=tool_use, tool_result
236
+ input: dict | None = None # type=tool_use, tool_result
237
+ message: str | None = None # type=error
238
+ ```
239
+
240
+ ## Development
241
+
242
+ ```bash
243
+ uv sync --dev # install dependencies
244
+ uv run pytest # run tests
245
+ ```
246
+
247
+ ## License
248
+
249
+ MIT
navdoc-0.2.4/README.md ADDED
@@ -0,0 +1,223 @@
1
+ # navdoc-py
2
+
3
+ Python SDK and CLI for [navdoc](https://dashboard.navdoc.dev). Upload and manage your documents via the navdoc REST API, and run RAG-powered chat with Claude.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install navdoc
9
+ ```
10
+
11
+ ## Credentials
12
+
13
+ ```bash
14
+ export NAVDOC_API_KEY=nd_...
15
+ ```
16
+
17
+ ## CLI
18
+
19
+ ### `navdoc ask`
20
+
21
+ Run a one-shot query.
22
+
23
+ ```bash
24
+ # Direct question
25
+ navdoc ask "What is asyncio?"
26
+ navdoc ask "What is asyncio?" --system-prompt "Be concise."
27
+
28
+ # Config-based
29
+ navdoc ask --config daily.json
30
+ navdoc ask --config daily.json --var date=2025-05-08
31
+ ```
32
+
33
+ Config format:
34
+
35
+ ```json
36
+ {
37
+ "name": "Daily Summary",
38
+ "description": "Summarize a day's lifelog entries with activity count and time-of-day trends",
39
+ "system_prompt": "You are a lifelog analyst. Respond in {{language}}.",
40
+ "user_prompt": "Please summarize the logs for {{date}}. Include the number of activities and time-of-day trends.",
41
+ "placeholders": [
42
+ {
43
+ "key": "date",
44
+ "label": "Target date",
45
+ "default": "today"
46
+ },
47
+ {
48
+ "key": "language",
49
+ "label": "Response language",
50
+ "default": "English"
51
+ }
52
+ ]
53
+ }
54
+ ```
55
+
56
+ - Both `system_prompt` and `user_prompt` support `{{key}}` placeholders.
57
+ - If `--var key=value` is not provided, missing placeholders are prompted interactively (unless a `default` is set).
58
+
59
+ ### `navdoc chat`
60
+
61
+ Start an interactive multi-turn chat session.
62
+
63
+ ```bash
64
+ # No config — plain chat
65
+ navdoc chat
66
+
67
+ # With a system prompt
68
+ navdoc chat --system-prompt "You are a helpful assistant."
69
+
70
+ # With a config file
71
+ navdoc chat --config qa.json
72
+ navdoc chat --config qa.json --var topic=asyncio
73
+ navdoc chat --config qa.json --no-initial-message
74
+ ```
75
+
76
+ `--config` is optional. If omitted, chat starts immediately with an empty (or `--system-prompt`-specified) prompt. If `user_prompt` is set in the config, it is sent as the first message automatically (`--no-initial-message` suppresses this). Type `exit` or press Ctrl+C to quit.
77
+
78
+ ## Python SDK
79
+
80
+ ### `NavdocClient`
81
+
82
+ ```python
83
+ from navdoc import NavdocClient
84
+
85
+ client = NavdocClient(
86
+ api_key="nd_...", # or NAVDOC_API_KEY env var
87
+ )
88
+ ```
89
+
90
+ ### Document management
91
+
92
+ Upload, list, and delete documents via the navdoc REST API.
93
+
94
+ #### `upload_document()`
95
+
96
+ ```python
97
+ from navdoc import NavdocClient, Document
98
+
99
+ doc = await client.upload_document(
100
+ "Full text content of the document...",
101
+ url="https://example.com/page", # unique identifier for the document
102
+ scope="my-scope", # optional
103
+ )
104
+ print(doc.document_id) # str
105
+ print(doc.chunk_count) # int
106
+ ```
107
+
108
+ #### `upload_chunks()`
109
+
110
+ Upload pre-split chunks instead of raw text (useful when you handle chunking yourself).
111
+
112
+ ```python
113
+ chunk_ids = await client.upload_chunks(
114
+ ["First chunk...", "Second chunk..."],
115
+ document_url="https://example.com/page",
116
+ scope="my-scope",
117
+ )
118
+ ```
119
+
120
+ #### `list_documents()`
121
+
122
+ ```python
123
+ docs = await client.list_documents(scope="my-scope", limit=50, offset=0)
124
+ for doc in docs:
125
+ print(doc.document_id, doc.chunk_count)
126
+ ```
127
+
128
+ #### `delete_document()`
129
+
130
+ ```python
131
+ await client.delete_document("doc_id_xxx")
132
+ ```
133
+
134
+ #### `Document` type
135
+
136
+ ```python
137
+ @dataclass
138
+ class Document:
139
+ document_id: str
140
+ chunk_count: int
141
+ ```
142
+
143
+ ### Scope management
144
+
145
+ Scopes are namespaces that group documents.
146
+
147
+ ```python
148
+ from navdoc import NavdocClient, Scope
149
+
150
+ scopes = await client.list_scopes()
151
+ scope = await client.create_scope("my-scope", visibility="private")
152
+ scope = await client.get_scope("my-scope")
153
+ scope = await client.update_scope("my-scope", visibility="public")
154
+ await client.delete_scope("my-scope") # also removes all documents inside
155
+ ```
156
+
157
+ #### `Scope` type
158
+
159
+ ```python
160
+ @dataclass
161
+ class Scope:
162
+ name: str
163
+ visibility: str # "private" | "public"
164
+ ```
165
+
166
+ ### Server-side agent
167
+
168
+ RAG chat powered by navdoc's built-in Claude agent.
169
+
170
+ #### `stream()` — streaming
171
+
172
+ Yields `StreamEvent` objects as the server sends them.
173
+
174
+ ```python
175
+ from navdoc import NavdocClient, StreamEvent
176
+
177
+ async for event in client.stream(
178
+ "What is asyncio?",
179
+ messages=[...], # optional conversation history
180
+ system_prompt="Answer concisely.",
181
+ timezone="Asia/Tokyo",
182
+ ):
183
+ if event.type == "text":
184
+ print(event.delta, end="", flush=True)
185
+ ```
186
+
187
+ #### `ask_server()` — non-streaming
188
+
189
+ Collects the full response and returns an `AgentResponse`.
190
+
191
+ ```python
192
+ response = await client.ask_server(
193
+ "What is asyncio?",
194
+ messages=[{"role": "user", "content": "previous turn"}, ...], # optional history
195
+ system_prompt="Answer concisely.",
196
+ timezone="Asia/Tokyo",
197
+ )
198
+ print(response.answer)
199
+ print(response.tool_calls)
200
+ ```
201
+
202
+ #### `StreamEvent` type
203
+
204
+ ```python
205
+ @dataclass
206
+ class StreamEvent:
207
+ type: str # "text" | "tool_use" | "tool_result" | "done" | "error"
208
+ delta: str | None = None # type=text
209
+ name: str | None = None # type=tool_use, tool_result
210
+ input: dict | None = None # type=tool_use, tool_result
211
+ message: str | None = None # type=error
212
+ ```
213
+
214
+ ## Development
215
+
216
+ ```bash
217
+ uv sync --dev # install dependencies
218
+ uv run pytest # run tests
219
+ ```
220
+
221
+ ## License
222
+
223
+ MIT
@@ -0,0 +1,14 @@
1
+ from .client import NavdocClient
2
+ from .models import AgentResponse, ToolCall, Document, Scope, StreamEvent
3
+ from .exceptions import NavdocError, AuthError
4
+
5
+ __all__ = [
6
+ "NavdocClient",
7
+ "AgentResponse",
8
+ "ToolCall",
9
+ "Document",
10
+ "Scope",
11
+ "StreamEvent",
12
+ "NavdocError",
13
+ "AuthError",
14
+ ]