karakeep-python-api 1.7.0__tar.gz → 1.9.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.
Files changed (18) hide show
  1. {karakeep_python_api-1.7.0/karakeep_python_api.egg-info → karakeep_python_api-1.9.0}/PKG-INFO +7 -2
  2. {karakeep_python_api-1.7.0 → karakeep_python_api-1.9.0}/README.md +6 -1
  3. {karakeep_python_api-1.7.0 → karakeep_python_api-1.9.0}/karakeep_python_api/__main__.py +17 -1
  4. {karakeep_python_api-1.7.0 → karakeep_python_api-1.9.0}/karakeep_python_api/datatypes.py +65 -2
  5. {karakeep_python_api-1.7.0 → karakeep_python_api-1.9.0}/karakeep_python_api/karakeep_api.py +433 -5
  6. {karakeep_python_api-1.7.0 → karakeep_python_api-1.9.0}/karakeep_python_api/openapi_reference.json +2000 -702
  7. {karakeep_python_api-1.7.0 → karakeep_python_api-1.9.0/karakeep_python_api.egg-info}/PKG-INFO +7 -2
  8. {karakeep_python_api-1.7.0 → karakeep_python_api-1.9.0}/setup.py +1 -1
  9. {karakeep_python_api-1.7.0 → karakeep_python_api-1.9.0}/tests/test_karakeep_api.py +522 -0
  10. {karakeep_python_api-1.7.0 → karakeep_python_api-1.9.0}/LICENSE +0 -0
  11. {karakeep_python_api-1.7.0 → karakeep_python_api-1.9.0}/MANIFEST.in +0 -0
  12. {karakeep_python_api-1.7.0 → karakeep_python_api-1.9.0}/karakeep_python_api/__init__.py +0 -0
  13. {karakeep_python_api-1.7.0 → karakeep_python_api-1.9.0}/karakeep_python_api.egg-info/SOURCES.txt +0 -0
  14. {karakeep_python_api-1.7.0 → karakeep_python_api-1.9.0}/karakeep_python_api.egg-info/dependency_links.txt +0 -0
  15. {karakeep_python_api-1.7.0 → karakeep_python_api-1.9.0}/karakeep_python_api.egg-info/entry_points.txt +0 -0
  16. {karakeep_python_api-1.7.0 → karakeep_python_api-1.9.0}/karakeep_python_api.egg-info/requires.txt +0 -0
  17. {karakeep_python_api-1.7.0 → karakeep_python_api-1.9.0}/karakeep_python_api.egg-info/top_level.txt +0 -0
  18. {karakeep_python_api-1.7.0 → karakeep_python_api-1.9.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: karakeep_python_api
3
- Version: 1.7.0
3
+ Version: 1.9.0
4
4
  Summary: Community python client for the Karakeep API.
5
5
  Home-page: https://github.com/thiswillbeyourgithub/karakeep_python_api/
6
6
  Keywords: rss,karakeep,hoarder,data-hoarding,python,api,feeds,openapi
@@ -82,6 +82,7 @@ Methods or CLI commands marked with ❌ should be used with caution as their beh
82
82
  | `get_a_single_bookmark` | ✅ | ❌ | |
83
83
  | `delete_a_bookmark` | ✅ | ❌ | |
84
84
  | `update_a_bookmark` | ✅ | ✅ | Tested for title updates. |
85
+ | `get_bookmark_readable_content` | ✅ | ❌ | Chunk merging tested offline; live test reads a text bookmark. |
85
86
  | `summarize_a_bookmark` | ❌ | ❌ | |
86
87
  | `attach_tags_to_a_bookmark` | ✅ | ❌ | |
87
88
  | `detach_tags_from_a_bookmark` | ✅ | ❌ | |
@@ -110,6 +111,7 @@ Methods or CLI commands marked with ❌ should be used with caution as their beh
110
111
  | `update_a_highlight` | ❌ | ❌ | |
111
112
  | `upload_a_new_asset` | ✅ | ❌ | Tested in PDF asset lifecycle test. |
112
113
  | `get_a_single_asset` | ✅ | ❌ | Tested in PDF asset lifecycle test. |
114
+ | `get_asset_signed_url` | ✅ | ❌ | Tested in PDF asset lifecycle test (downloads without an API key). |
113
115
  | `get_current_user_info` | ✅ | ❌ | Pytest: Tested indirectly during client init. CLI not directly tested. |
114
116
  | `get_current_user_stats` | ✅ | ✅ | |
115
117
  | `update_user` | ❌ | ❌ | |
@@ -118,6 +120,9 @@ Methods or CLI commands marked with ❌ should be used with caution as their beh
118
120
  | `get_a_single_backup` | ✅ | ❌ | Tested in backup lifecycle test. |
119
121
  | `delete_a_backup` | ✅ | ❌ | Tested in backup lifecycle test. |
120
122
  | `download_a_backup` | ✅ | ❌ | Tested in backup lifecycle test. |
123
+ | `admin_trigger_recrawl` | ❌ | ❌ | Request body construction tested offline only. |
124
+ | `admin_trigger_reindex` | ❌ | ❌ | Request body construction tested offline only. |
125
+ | `admin_trigger_inference` | ❌ | ❌ | Request body construction tested offline only. |
121
126
 
122
127
  ## Installation
123
128
 
@@ -281,4 +286,4 @@ They can be found in the [./community_scripts](https://github.com/thiswillbeyour
281
286
 
282
287
  ---
283
288
 
284
- *This README was generated with assistance from [aider.chat](https://aider.chat).*
289
+ *This README was generated with assistance from [aider.chat](https://aider.chat), and later kept up to date with [Claude Code](https://claude.com/claude-code).*
@@ -50,6 +50,7 @@ Methods or CLI commands marked with ❌ should be used with caution as their beh
50
50
  | `get_a_single_bookmark` | ✅ | ❌ | |
51
51
  | `delete_a_bookmark` | ✅ | ❌ | |
52
52
  | `update_a_bookmark` | ✅ | ✅ | Tested for title updates. |
53
+ | `get_bookmark_readable_content` | ✅ | ❌ | Chunk merging tested offline; live test reads a text bookmark. |
53
54
  | `summarize_a_bookmark` | ❌ | ❌ | |
54
55
  | `attach_tags_to_a_bookmark` | ✅ | ❌ | |
55
56
  | `detach_tags_from_a_bookmark` | ✅ | ❌ | |
@@ -78,6 +79,7 @@ Methods or CLI commands marked with ❌ should be used with caution as their beh
78
79
  | `update_a_highlight` | ❌ | ❌ | |
79
80
  | `upload_a_new_asset` | ✅ | ❌ | Tested in PDF asset lifecycle test. |
80
81
  | `get_a_single_asset` | ✅ | ❌ | Tested in PDF asset lifecycle test. |
82
+ | `get_asset_signed_url` | ✅ | ❌ | Tested in PDF asset lifecycle test (downloads without an API key). |
81
83
  | `get_current_user_info` | ✅ | ❌ | Pytest: Tested indirectly during client init. CLI not directly tested. |
82
84
  | `get_current_user_stats` | ✅ | ✅ | |
83
85
  | `update_user` | ❌ | ❌ | |
@@ -86,6 +88,9 @@ Methods or CLI commands marked with ❌ should be used with caution as their beh
86
88
  | `get_a_single_backup` | ✅ | ❌ | Tested in backup lifecycle test. |
87
89
  | `delete_a_backup` | ✅ | ❌ | Tested in backup lifecycle test. |
88
90
  | `download_a_backup` | ✅ | ❌ | Tested in backup lifecycle test. |
91
+ | `admin_trigger_recrawl` | ❌ | ❌ | Request body construction tested offline only. |
92
+ | `admin_trigger_reindex` | ❌ | ❌ | Request body construction tested offline only. |
93
+ | `admin_trigger_inference` | ❌ | ❌ | Request body construction tested offline only. |
89
94
 
90
95
  ## Installation
91
96
 
@@ -249,4 +254,4 @@ They can be found in the [./community_scripts](https://github.com/thiswillbeyour
249
254
 
250
255
  ---
251
256
 
252
- *This README was generated with assistance from [aider.chat](https://aider.chat).*
257
+ *This README was generated with assistance from [aider.chat](https://aider.chat), and later kept up to date with [Claude Code](https://claude.com/claude-code).*
@@ -538,7 +538,23 @@ def create_click_command(
538
538
  ctx.exit(1)
539
539
 
540
540
  # Serialize and print the result
541
- if result is not None:
541
+ if isinstance(result, (bytes, bytearray)):
542
+ # Binary payloads (e.g. download_a_backup, get_a_single_asset)
543
+ # cannot be JSON encoded: write them raw to stdout so the
544
+ # output can be redirected straight into a file.
545
+ logger.debug(f"Writing {len(result)} raw bytes to stdout.")
546
+ stdout_buffer = getattr(sys.stdout, "buffer", None)
547
+ if stdout_buffer is not None:
548
+ stdout_buffer.write(result)
549
+ stdout_buffer.flush()
550
+ else:
551
+ # Some test/capture harnesses replace sys.stdout with a
552
+ # text-only stream that has no .buffer attribute.
553
+ sys.stdout.write(
554
+ bytes(result).decode("utf-8", errors="surrogateescape")
555
+ )
556
+ sys.stdout.flush()
557
+ elif result is not None:
542
558
  output_data = serialize_output(result)
543
559
  # Use ensure_ascii_output flag to control JSON encoding
544
560
  click.echo(
@@ -53,6 +53,15 @@ class ContentTypeLink(BaseModel):
53
53
  favicon: Optional[str] = None
54
54
  htmlContent: Optional[str] = None
55
55
  contentAssetId: Optional[str] = None
56
+ # Reader-view triage produced by the crawler: readerViewStatus says whether a
57
+ # distraction-free rendering could be extracted, readerViewScore (0-100) how
58
+ # confident that extraction is, and preferredPreview which of the available
59
+ # renderings the UI should show by default.
60
+ readerViewStatus: Optional[
61
+ Literal["readable", "not_readable", "uncertain", "unavailable"]
62
+ ] = None
63
+ readerViewScore: Optional[int] = None
64
+ preferredPreview: Optional[Literal["reader_view", "screenshot", "overview"]] = None
56
65
  crawledAt: Optional[str] = None
57
66
  crawlStatus: Optional[Literal["success", "failure", "pending"]] = None
58
67
  author: Optional[str] = None
@@ -100,22 +109,43 @@ class BookmarkAsset(BaseModel):
100
109
  fileName: Optional[str] = None
101
110
 
102
111
 
103
- class Asset(BaseModel):
112
+ class UploadedAsset(BaseModel):
104
113
  assetId: str
105
114
  contentType: str
106
115
  size: float
107
116
  fileName: str
108
117
 
109
118
 
119
+ # Backwards-compatible alias: the upstream OpenAPI schema was renamed
120
+ # from "Asset" to "UploadedAsset".
121
+ Asset = UploadedAsset
122
+
123
+
124
+ class SignedAssetUrl(BaseModel):
125
+ assetId: str
126
+ # Temporary download URL that carries its own signature, so it works without
127
+ # the Authorization header and can be handed to a browser or media player.
128
+ signedUrl: str
129
+ expiresAt: str
130
+
131
+
110
132
  class Bookmark(BaseModel):
111
133
  id: str
134
+ # firstCreatedAt records the original creation time when a bookmark is
135
+ # recreated/re-imported, so it can predate createdAt. Optional in the spec
136
+ # and absent on Karakeep servers older than the one that introduced it.
137
+ firstCreatedAt: Optional[str] = None
112
138
  createdAt: str
113
139
  modifiedAt: Optional[str]
114
140
  title: Optional[str] = None
115
141
  archived: bool
116
142
  favourited: bool
117
- taggingStatus: Literal["success", "failure", "pending"]
143
+ taggingStatus: Optional[Literal["success", "failure", "pending"]] = None
118
144
  summarizationStatus: Optional[Literal["success", "failure", "pending"]] = None
145
+ # Status of the vector-embedding job used by semantic/hybrid search. The
146
+ # spec marks it required-but-nullable, so no default is given here: a
147
+ # missing key is a genuine mismatch with the documented server response.
148
+ embeddingStatus: Optional[Literal["success", "failure", "pending"]]
119
149
  note: Optional[str] = None
120
150
  summary: Optional[str] = None
121
151
  source: Optional[
@@ -131,6 +161,28 @@ class Bookmark(BaseModel):
131
161
  assets: List[BookmarkAsset]
132
162
 
133
163
 
164
+ class ReadableContentRange(BaseModel):
165
+ # Offsets are in Unicode characters over the *rendered* content, not bytes:
166
+ # start is inclusive, end is exclusive, and total is the full rendered length.
167
+ start: int
168
+ end: int
169
+ total: int
170
+
171
+
172
+ class BookmarkReadableContent(BaseModel):
173
+ bookmarkId: str
174
+ bookmarkType: Literal["link", "text", "asset"]
175
+ format: Literal["markdown", "text"]
176
+ content: str
177
+ # Hash of the rendered content the cursor was issued against. The server
178
+ # answers 409 if the bookmark changed between two chunks, so this value must
179
+ # not be mixed across a paginated read.
180
+ contentVersion: str
181
+ range: ReadableContentRange
182
+ nextCursor: Optional[str]
183
+ truncated: bool
184
+
185
+
134
186
  class PaginatedBookmarks(BaseModel):
135
187
  bookmarks: List[Bookmark]
136
188
  nextCursor: Optional[str] = ""
@@ -184,3 +236,14 @@ class Backup(BaseModel):
184
236
  bookmarkCount: int
185
237
  status: Literal["pending", "success", "failure"]
186
238
  errorMessage: Optional[str] = None
239
+
240
+
241
+ class Feed(BaseModel):
242
+ id: str
243
+ name: str
244
+ url: str
245
+ enabled: bool
246
+ importTags: bool
247
+ lastFetchedStatus: Optional[Literal["success", "failure", "pending"]]
248
+ lastFetchedAt: Optional[str]
249
+ lastSuccessfulFetchAt: Optional[str]