karakeep-python-api 1.8.0__py3-none-any.whl → 1.9.0__py3-none-any.whl
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.
- karakeep_python_api/__main__.py +17 -1
- karakeep_python_api/datatypes.py +47 -0
- karakeep_python_api/karakeep_api.py +188 -8
- karakeep_python_api/openapi_reference.json +379 -8
- {karakeep_python_api-1.8.0.dist-info → karakeep_python_api-1.9.0.dist-info}/METADATA +7 -2
- karakeep_python_api-1.9.0.dist-info/RECORD +11 -0
- {karakeep_python_api-1.8.0.dist-info → karakeep_python_api-1.9.0.dist-info}/WHEEL +1 -1
- karakeep_python_api-1.8.0.dist-info/RECORD +0 -11
- {karakeep_python_api-1.8.0.dist-info → karakeep_python_api-1.9.0.dist-info}/entry_points.txt +0 -0
- {karakeep_python_api-1.8.0.dist-info → karakeep_python_api-1.9.0.dist-info}/licenses/LICENSE +0 -0
- {karakeep_python_api-1.8.0.dist-info → karakeep_python_api-1.9.0.dist-info}/top_level.txt +0 -0
karakeep_python_api/__main__.py
CHANGED
|
@@ -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
|
|
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(
|
karakeep_python_api/datatypes.py
CHANGED
|
@@ -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
|
|
@@ -112,8 +121,20 @@ class UploadedAsset(BaseModel):
|
|
|
112
121
|
Asset = UploadedAsset
|
|
113
122
|
|
|
114
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
|
+
|
|
115
132
|
class Bookmark(BaseModel):
|
|
116
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
|
|
117
138
|
createdAt: str
|
|
118
139
|
modifiedAt: Optional[str]
|
|
119
140
|
title: Optional[str] = None
|
|
@@ -121,6 +142,10 @@ class Bookmark(BaseModel):
|
|
|
121
142
|
favourited: bool
|
|
122
143
|
taggingStatus: Optional[Literal["success", "failure", "pending"]] = None
|
|
123
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"]]
|
|
124
149
|
note: Optional[str] = None
|
|
125
150
|
summary: Optional[str] = None
|
|
126
151
|
source: Optional[
|
|
@@ -136,6 +161,28 @@ class Bookmark(BaseModel):
|
|
|
136
161
|
assets: List[BookmarkAsset]
|
|
137
162
|
|
|
138
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
|
+
|
|
139
186
|
class PaginatedBookmarks(BaseModel):
|
|
140
187
|
bookmarks: List[Bookmark]
|
|
141
188
|
nextCursor: Optional[str] = ""
|
|
@@ -85,7 +85,7 @@ class KarakeepAPI:
|
|
|
85
85
|
"""
|
|
86
86
|
|
|
87
87
|
# Version reflects the client library version, updated by bumpver
|
|
88
|
-
VERSION: str = "1.
|
|
88
|
+
VERSION: str = "1.9.0"
|
|
89
89
|
|
|
90
90
|
def __init__(
|
|
91
91
|
self,
|
|
@@ -891,16 +891,25 @@ class KarakeepAPI:
|
|
|
891
891
|
def search_bookmarks(
|
|
892
892
|
self,
|
|
893
893
|
q: str, # Search query is required
|
|
894
|
+
search_mode: Optional[Literal["fts", "semantic", "hybrid"]] = None,
|
|
894
895
|
sort_order: Optional[Literal["asc", "desc", "relevance"]] = None,
|
|
895
896
|
limit: Optional[int] = None,
|
|
896
897
|
cursor: Optional[str] = None,
|
|
897
898
|
include_content: bool = True, # Default from spec
|
|
898
899
|
) -> Union[datatypes.PaginatedBookmarks, Dict[str, Any], List[Any]]:
|
|
899
900
|
"""
|
|
900
|
-
Search bookmarks
|
|
901
|
+
Search bookmarks using full-text, semantic or hybrid ranking.
|
|
902
|
+
Corresponds to GET /bookmarks/search.
|
|
901
903
|
|
|
902
904
|
Args:
|
|
903
905
|
q: The search query string.
|
|
906
|
+
search_mode: Search strategy (optional). "fts" is full-text search (API default),
|
|
907
|
+
"semantic" ranks with bookmark embeddings, and "hybrid" fuses both.
|
|
908
|
+
Hybrid falls back to full-text search when the query has no free-text
|
|
909
|
+
terms or when embedding infrastructure is unavailable. Semantic hits
|
|
910
|
+
below a minimum similarity are dropped, so "semantic" and "hybrid" may
|
|
911
|
+
return fewer results than `limit`. Note that the semantic modes only
|
|
912
|
+
support sort_order="relevance".
|
|
904
913
|
sort_order: Sort order for results ("asc", "desc", "relevance"). Default from API is "relevance" (optional).
|
|
905
914
|
limit: Maximum number of bookmarks to return (optional).
|
|
906
915
|
cursor: Pagination cursor for the next page (optional).
|
|
@@ -916,6 +925,7 @@ class KarakeepAPI:
|
|
|
916
925
|
"""
|
|
917
926
|
params = {
|
|
918
927
|
"q": q,
|
|
928
|
+
"searchMode": search_mode,
|
|
919
929
|
"sortOrder": sort_order,
|
|
920
930
|
"limit": limit,
|
|
921
931
|
"cursor": cursor,
|
|
@@ -1051,6 +1061,101 @@ class KarakeepAPI:
|
|
|
1051
1061
|
# No Pydantic validation applied here as the spec defines a partial response (dict)
|
|
1052
1062
|
return response_data
|
|
1053
1063
|
|
|
1064
|
+
@optional_typecheck
|
|
1065
|
+
def get_bookmark_readable_content(
|
|
1066
|
+
self,
|
|
1067
|
+
bookmark_id: str,
|
|
1068
|
+
format: Optional[Literal["markdown", "text"]] = None,
|
|
1069
|
+
max_chars: Optional[int] = None,
|
|
1070
|
+
cursor: Optional[str] = None,
|
|
1071
|
+
fetch_all: bool = False,
|
|
1072
|
+
) -> Union[datatypes.BookmarkReadableContent, Dict[str, Any], List[Any]]:
|
|
1073
|
+
"""
|
|
1074
|
+
Get an agent-readable rendering of a bookmark's content.
|
|
1075
|
+
Corresponds to GET /bookmarks/{bookmarkId}/content.
|
|
1076
|
+
|
|
1077
|
+
Link content is rendered from the extracted HTML; text and asset bookmarks use
|
|
1078
|
+
their stored or extracted text. The endpoint returns a bounded chunk plus an
|
|
1079
|
+
opaque `nextCursor`; pass that cursor back to continue reading, or set
|
|
1080
|
+
`fetch_all=True` to let this method walk the cursors and return the whole
|
|
1081
|
+
document as a single object.
|
|
1082
|
+
|
|
1083
|
+
Args:
|
|
1084
|
+
bookmark_id: The ID (string) of the bookmark to read.
|
|
1085
|
+
format: Readable representation, "markdown" or "text" (optional). If omitted
|
|
1086
|
+
together with a cursor, the cursor's own format is reused; otherwise
|
|
1087
|
+
the API defaults to "markdown".
|
|
1088
|
+
max_chars: Maximum number of Unicode characters per chunk, 1 to 50000
|
|
1089
|
+
(optional, API default 12000). A chunk may end earlier, at a
|
|
1090
|
+
paragraph or line boundary.
|
|
1091
|
+
cursor: Opaque continuation cursor returned as `nextCursor` by a previous
|
|
1092
|
+
response (optional).
|
|
1093
|
+
fetch_all: If True, keep following `nextCursor` until the document is
|
|
1094
|
+
exhausted and return one merged object whose `content` is the
|
|
1095
|
+
concatenation of every chunk, with `nextCursor=None` and
|
|
1096
|
+
`truncated=False` (default: False).
|
|
1097
|
+
|
|
1098
|
+
Returns:
|
|
1099
|
+
datatypes.BookmarkReadableContent: A chunk of readable content (or the whole
|
|
1100
|
+
document when fetch_all is True).
|
|
1101
|
+
If response validation is disabled, returns the raw API response (dict/list).
|
|
1102
|
+
|
|
1103
|
+
Raises:
|
|
1104
|
+
APIError: If the API request fails (e.g. 404 bookmark not found, or 409 if
|
|
1105
|
+
the bookmark content changed after the supplied cursor was issued).
|
|
1106
|
+
pydantic.ValidationError: If response validation fails (and is not disabled).
|
|
1107
|
+
"""
|
|
1108
|
+
endpoint = f"bookmarks/{bookmark_id}/content"
|
|
1109
|
+
params = {
|
|
1110
|
+
"format": format,
|
|
1111
|
+
"maxChars": max_chars,
|
|
1112
|
+
"cursor": cursor,
|
|
1113
|
+
}
|
|
1114
|
+
response_data = self._call("GET", endpoint, params=params)
|
|
1115
|
+
|
|
1116
|
+
if fetch_all:
|
|
1117
|
+
# Walk the cursor chain and merge the chunks. The raw dicts are merged
|
|
1118
|
+
# rather than the validated models so that the loop behaves identically
|
|
1119
|
+
# whether or not response validation is enabled.
|
|
1120
|
+
if not isinstance(response_data, dict):
|
|
1121
|
+
raise APIError(
|
|
1122
|
+
f"Unexpected response format for get_bookmark_readable_content: {response_data}"
|
|
1123
|
+
)
|
|
1124
|
+
merged = dict(response_data)
|
|
1125
|
+
chunks = [merged.get("content", "")]
|
|
1126
|
+
next_cursor = merged.get("nextCursor")
|
|
1127
|
+
while next_cursor:
|
|
1128
|
+
params["cursor"] = next_cursor
|
|
1129
|
+
# The format is carried by the cursor itself, so it is left as passed.
|
|
1130
|
+
page = self._call("GET", endpoint, params=params)
|
|
1131
|
+
if not isinstance(page, dict):
|
|
1132
|
+
raise APIError(
|
|
1133
|
+
f"Unexpected response format for get_bookmark_readable_content: {page}"
|
|
1134
|
+
)
|
|
1135
|
+
chunks.append(page.get("content", ""))
|
|
1136
|
+
# Keep the latest range end/total: the server may only know the true
|
|
1137
|
+
# total once it has rendered further into the document.
|
|
1138
|
+
if "range" in page and "range" in merged:
|
|
1139
|
+
merged["range"] = {
|
|
1140
|
+
**page["range"],
|
|
1141
|
+
"start": merged["range"].get("start", 0),
|
|
1142
|
+
}
|
|
1143
|
+
merged["contentVersion"] = page.get(
|
|
1144
|
+
"contentVersion", merged.get("contentVersion")
|
|
1145
|
+
)
|
|
1146
|
+
next_cursor = page.get("nextCursor")
|
|
1147
|
+
merged["content"] = "".join(chunks)
|
|
1148
|
+
merged["nextCursor"] = None
|
|
1149
|
+
merged["truncated"] = False
|
|
1150
|
+
response_data = merged
|
|
1151
|
+
|
|
1152
|
+
if self.disable_response_validation:
|
|
1153
|
+
logger.debug("Skipping response validation as requested.")
|
|
1154
|
+
return response_data
|
|
1155
|
+
else:
|
|
1156
|
+
# Response should match BookmarkReadableContent schema
|
|
1157
|
+
return datatypes.BookmarkReadableContent.model_validate(response_data)
|
|
1158
|
+
|
|
1054
1159
|
@optional_typecheck
|
|
1055
1160
|
def summarize_a_bookmark(self, bookmark_id: str) -> Dict[str, Any]:
|
|
1056
1161
|
"""
|
|
@@ -2481,6 +2586,44 @@ class KarakeepAPI:
|
|
|
2481
2586
|
logger.error(error_msg)
|
|
2482
2587
|
raise APIError(error_msg)
|
|
2483
2588
|
|
|
2589
|
+
@optional_typecheck
|
|
2590
|
+
def get_asset_signed_url(
|
|
2591
|
+
self, asset_id: str
|
|
2592
|
+
) -> Union[datatypes.SignedAssetUrl, Dict[str, Any], List[Any]]:
|
|
2593
|
+
"""
|
|
2594
|
+
Get a temporary signed URL for downloading an asset.
|
|
2595
|
+
Corresponds to GET /assets/{assetId}/signed-url.
|
|
2596
|
+
|
|
2597
|
+
The returned URL embeds its own signature and expiry, so it can be fetched
|
|
2598
|
+
without an API key. This is the way to hand an asset to something that cannot
|
|
2599
|
+
send the Authorization header (a browser tab, a media player, an <img> tag)
|
|
2600
|
+
without proxying the bytes through get_a_single_asset.
|
|
2601
|
+
|
|
2602
|
+
Args:
|
|
2603
|
+
asset_id: The ID (string) of the asset to sign.
|
|
2604
|
+
|
|
2605
|
+
Returns:
|
|
2606
|
+
datatypes.SignedAssetUrl: The asset id, the temporary URL and its expiry.
|
|
2607
|
+
If response validation is disabled, returns the raw API response (dict/list).
|
|
2608
|
+
|
|
2609
|
+
Raises:
|
|
2610
|
+
APIError: If the API request fails.
|
|
2611
|
+
ValueError: If asset_id is empty.
|
|
2612
|
+
pydantic.ValidationError: If response validation fails (and is not disabled).
|
|
2613
|
+
"""
|
|
2614
|
+
if not asset_id or not asset_id.strip():
|
|
2615
|
+
raise ValueError("asset_id cannot be empty")
|
|
2616
|
+
|
|
2617
|
+
endpoint = f"assets/{asset_id.strip()}/signed-url"
|
|
2618
|
+
response_data = self._call("GET", endpoint)
|
|
2619
|
+
|
|
2620
|
+
if self.disable_response_validation:
|
|
2621
|
+
logger.debug("Skipping response validation as requested.")
|
|
2622
|
+
return response_data
|
|
2623
|
+
else:
|
|
2624
|
+
# Response should match SignedAssetUrl schema
|
|
2625
|
+
return datatypes.SignedAssetUrl.model_validate(response_data)
|
|
2626
|
+
|
|
2484
2627
|
# --- Admin: Job Triggers ---
|
|
2485
2628
|
|
|
2486
2629
|
@optional_typecheck
|
|
@@ -2488,6 +2631,7 @@ class KarakeepAPI:
|
|
|
2488
2631
|
self,
|
|
2489
2632
|
crawl_status: Literal["success", "failure", "pending", "all"] = "all",
|
|
2490
2633
|
run_inference: bool = False,
|
|
2634
|
+
modified_within_seconds: Optional[int] = None,
|
|
2491
2635
|
) -> Dict[str, Any]:
|
|
2492
2636
|
"""
|
|
2493
2637
|
Trigger a recrawl of link bookmarks. Admin only.
|
|
@@ -2497,6 +2641,9 @@ class KarakeepAPI:
|
|
|
2497
2641
|
crawl_status: Filter bookmarks by their current crawl status.
|
|
2498
2642
|
Use "failure" to retry only failed crawls. Default: "all".
|
|
2499
2643
|
run_inference: Whether to run AI inference after crawling. Default: False.
|
|
2644
|
+
modified_within_seconds: Only process bookmarks modified within this many
|
|
2645
|
+
seconds. Must be > 0. Omit to process all matching
|
|
2646
|
+
bookmarks (optional).
|
|
2500
2647
|
|
|
2501
2648
|
Returns:
|
|
2502
2649
|
dict: A dictionary with a "success" boolean field.
|
|
@@ -2504,16 +2651,34 @@ class KarakeepAPI:
|
|
|
2504
2651
|
Raises:
|
|
2505
2652
|
APIError: If the API request fails (e.g., 403 admin access required).
|
|
2506
2653
|
"""
|
|
2507
|
-
body
|
|
2654
|
+
body: Dict[str, Any] = {
|
|
2655
|
+
"crawlStatus": crawl_status,
|
|
2656
|
+
"runInference": run_inference,
|
|
2657
|
+
}
|
|
2658
|
+
# Omitted rather than sent as null: the spec has no null case and the
|
|
2659
|
+
# absence of the key is what means "no time window".
|
|
2660
|
+
if modified_within_seconds is not None:
|
|
2661
|
+
body["modifiedWithinSeconds"] = modified_within_seconds
|
|
2508
2662
|
return self._call("POST", "admin/jobs/trigger/recrawl", data=body)
|
|
2509
2663
|
|
|
2510
2664
|
@optional_typecheck
|
|
2511
|
-
def admin_trigger_reindex(
|
|
2665
|
+
def admin_trigger_reindex(
|
|
2666
|
+
self,
|
|
2667
|
+
modified_within_seconds: Optional[int] = None,
|
|
2668
|
+
) -> Dict[str, Any]:
|
|
2512
2669
|
"""
|
|
2513
|
-
Trigger a reindex of
|
|
2670
|
+
Trigger a reindex of bookmarks in the search engine. Admin only.
|
|
2514
2671
|
Corresponds to POST /admin/jobs/trigger/reindex.
|
|
2515
2672
|
|
|
2516
|
-
|
|
2673
|
+
Without modified_within_seconds this clears the existing index and re-queues
|
|
2674
|
+
every bookmark. With it, only bookmarks modified within that window are
|
|
2675
|
+
re-queued and the existing index is left in place, which makes it usable as a
|
|
2676
|
+
cheap catch-up job rather than a full rebuild.
|
|
2677
|
+
|
|
2678
|
+
Args:
|
|
2679
|
+
modified_within_seconds: Only process bookmarks modified within this many
|
|
2680
|
+
seconds. Must be > 0. Omit to reindex everything
|
|
2681
|
+
from scratch (optional).
|
|
2517
2682
|
|
|
2518
2683
|
Returns:
|
|
2519
2684
|
dict: A dictionary with a "success" boolean field.
|
|
@@ -2521,13 +2686,22 @@ class KarakeepAPI:
|
|
|
2521
2686
|
Raises:
|
|
2522
2687
|
APIError: If the API request fails (e.g., 403 admin access required).
|
|
2523
2688
|
"""
|
|
2524
|
-
|
|
2689
|
+
# The request body is optional in the spec, so nothing is sent when no window
|
|
2690
|
+
# is given; that keeps the "clear and rebuild" behaviour byte-identical to
|
|
2691
|
+
# what older servers expect.
|
|
2692
|
+
body = (
|
|
2693
|
+
None
|
|
2694
|
+
if modified_within_seconds is None
|
|
2695
|
+
else {"modifiedWithinSeconds": modified_within_seconds}
|
|
2696
|
+
)
|
|
2697
|
+
return self._call("POST", "admin/jobs/trigger/reindex", data=body)
|
|
2525
2698
|
|
|
2526
2699
|
@optional_typecheck
|
|
2527
2700
|
def admin_trigger_inference(
|
|
2528
2701
|
self,
|
|
2529
2702
|
type: Literal["tag", "summarize"],
|
|
2530
2703
|
status: Literal["success", "failure", "pending", "all"] = "all",
|
|
2704
|
+
modified_within_seconds: Optional[int] = None,
|
|
2531
2705
|
) -> Dict[str, Any]:
|
|
2532
2706
|
"""
|
|
2533
2707
|
Trigger AI inference (tagging or summarization) on bookmarks. Admin only.
|
|
@@ -2538,6 +2712,9 @@ class KarakeepAPI:
|
|
|
2538
2712
|
"summarize" for AI summarization.
|
|
2539
2713
|
status: Filter bookmarks by their current inference status.
|
|
2540
2714
|
Use "failure" to retry only failed ones. Default: "all".
|
|
2715
|
+
modified_within_seconds: Only process bookmarks modified within this many
|
|
2716
|
+
seconds. Must be > 0. Omit to process all matching
|
|
2717
|
+
bookmarks (optional).
|
|
2541
2718
|
|
|
2542
2719
|
Returns:
|
|
2543
2720
|
dict: A dictionary with a "success" boolean field.
|
|
@@ -2545,7 +2722,10 @@ class KarakeepAPI:
|
|
|
2545
2722
|
Raises:
|
|
2546
2723
|
APIError: If the API request fails (e.g., 403 admin access required).
|
|
2547
2724
|
"""
|
|
2548
|
-
body = {"type": type, "status": status}
|
|
2725
|
+
body: Dict[str, Any] = {"type": type, "status": status}
|
|
2726
|
+
# See admin_trigger_recrawl: the key is omitted rather than sent as null.
|
|
2727
|
+
if modified_within_seconds is not None:
|
|
2728
|
+
body["modifiedWithinSeconds"] = modified_within_seconds
|
|
2549
2729
|
return self._call("POST", "admin/jobs/trigger/inference", data=body)
|
|
2550
2730
|
|
|
2551
2731
|
# --- Feeds ---
|
|
@@ -124,6 +124,10 @@
|
|
|
124
124
|
"id": {
|
|
125
125
|
"type": "string"
|
|
126
126
|
},
|
|
127
|
+
"firstCreatedAt": {
|
|
128
|
+
"type": "string",
|
|
129
|
+
"format": "date-time"
|
|
130
|
+
},
|
|
127
131
|
"createdAt": {
|
|
128
132
|
"type": "string",
|
|
129
133
|
"format": "date-time"
|
|
@@ -163,6 +167,16 @@
|
|
|
163
167
|
null
|
|
164
168
|
]
|
|
165
169
|
},
|
|
170
|
+
"embeddingStatus": {
|
|
171
|
+
"type": "string",
|
|
172
|
+
"nullable": true,
|
|
173
|
+
"enum": [
|
|
174
|
+
"success",
|
|
175
|
+
"failure",
|
|
176
|
+
"pending",
|
|
177
|
+
null
|
|
178
|
+
]
|
|
179
|
+
},
|
|
166
180
|
"note": {
|
|
167
181
|
"type": "string",
|
|
168
182
|
"nullable": true
|
|
@@ -277,6 +291,33 @@
|
|
|
277
291
|
"type": "string",
|
|
278
292
|
"nullable": true
|
|
279
293
|
},
|
|
294
|
+
"readerViewStatus": {
|
|
295
|
+
"type": "string",
|
|
296
|
+
"nullable": true,
|
|
297
|
+
"enum": [
|
|
298
|
+
"readable",
|
|
299
|
+
"not_readable",
|
|
300
|
+
"uncertain",
|
|
301
|
+
"unavailable",
|
|
302
|
+
null
|
|
303
|
+
]
|
|
304
|
+
},
|
|
305
|
+
"readerViewScore": {
|
|
306
|
+
"type": "integer",
|
|
307
|
+
"nullable": true,
|
|
308
|
+
"minimum": 0,
|
|
309
|
+
"maximum": 100
|
|
310
|
+
},
|
|
311
|
+
"preferredPreview": {
|
|
312
|
+
"type": "string",
|
|
313
|
+
"nullable": true,
|
|
314
|
+
"enum": [
|
|
315
|
+
"reader_view",
|
|
316
|
+
"screenshot",
|
|
317
|
+
"overview",
|
|
318
|
+
null
|
|
319
|
+
]
|
|
320
|
+
},
|
|
280
321
|
"crawledAt": {
|
|
281
322
|
"type": "string",
|
|
282
323
|
"nullable": true,
|
|
@@ -441,6 +482,7 @@
|
|
|
441
482
|
"favourited",
|
|
442
483
|
"taggingStatus",
|
|
443
484
|
"summarizationStatus",
|
|
485
|
+
"embeddingStatus",
|
|
444
486
|
"userId",
|
|
445
487
|
"tags",
|
|
446
488
|
"content",
|
|
@@ -468,6 +510,77 @@
|
|
|
468
510
|
"message"
|
|
469
511
|
]
|
|
470
512
|
},
|
|
513
|
+
"BookmarkReadableContent": {
|
|
514
|
+
"type": "object",
|
|
515
|
+
"properties": {
|
|
516
|
+
"bookmarkId": {
|
|
517
|
+
"type": "string"
|
|
518
|
+
},
|
|
519
|
+
"bookmarkType": {
|
|
520
|
+
"type": "string",
|
|
521
|
+
"enum": [
|
|
522
|
+
"link",
|
|
523
|
+
"text",
|
|
524
|
+
"asset"
|
|
525
|
+
]
|
|
526
|
+
},
|
|
527
|
+
"format": {
|
|
528
|
+
"type": "string",
|
|
529
|
+
"enum": [
|
|
530
|
+
"markdown",
|
|
531
|
+
"text"
|
|
532
|
+
]
|
|
533
|
+
},
|
|
534
|
+
"content": {
|
|
535
|
+
"type": "string"
|
|
536
|
+
},
|
|
537
|
+
"contentVersion": {
|
|
538
|
+
"type": "string",
|
|
539
|
+
"description": "A hash identifying the rendered content version used by this cursor."
|
|
540
|
+
},
|
|
541
|
+
"range": {
|
|
542
|
+
"type": "object",
|
|
543
|
+
"properties": {
|
|
544
|
+
"start": {
|
|
545
|
+
"type": "integer",
|
|
546
|
+
"description": "Zero-based start offset in Unicode characters, inclusive."
|
|
547
|
+
},
|
|
548
|
+
"end": {
|
|
549
|
+
"type": "integer",
|
|
550
|
+
"description": "Zero-based end offset in Unicode characters, exclusive."
|
|
551
|
+
},
|
|
552
|
+
"total": {
|
|
553
|
+
"type": "integer",
|
|
554
|
+
"description": "Total number of Unicode characters in the rendered content."
|
|
555
|
+
}
|
|
556
|
+
},
|
|
557
|
+
"required": [
|
|
558
|
+
"start",
|
|
559
|
+
"end",
|
|
560
|
+
"total"
|
|
561
|
+
]
|
|
562
|
+
},
|
|
563
|
+
"nextCursor": {
|
|
564
|
+
"type": "string",
|
|
565
|
+
"nullable": true,
|
|
566
|
+
"description": "Cursor for the next chunk, or null when all content has been returned."
|
|
567
|
+
},
|
|
568
|
+
"truncated": {
|
|
569
|
+
"type": "boolean",
|
|
570
|
+
"description": "Whether more readable content remains after this chunk."
|
|
571
|
+
}
|
|
572
|
+
},
|
|
573
|
+
"required": [
|
|
574
|
+
"bookmarkId",
|
|
575
|
+
"bookmarkType",
|
|
576
|
+
"format",
|
|
577
|
+
"content",
|
|
578
|
+
"contentVersion",
|
|
579
|
+
"range",
|
|
580
|
+
"nextCursor",
|
|
581
|
+
"truncated"
|
|
582
|
+
]
|
|
583
|
+
},
|
|
471
584
|
"List": {
|
|
472
585
|
"type": "object",
|
|
473
586
|
"properties": {
|
|
@@ -656,6 +769,30 @@
|
|
|
656
769
|
"fileName"
|
|
657
770
|
]
|
|
658
771
|
},
|
|
772
|
+
"SignedAssetUrl": {
|
|
773
|
+
"type": "object",
|
|
774
|
+
"properties": {
|
|
775
|
+
"assetId": {
|
|
776
|
+
"type": "string",
|
|
777
|
+
"description": "The unique identifier of the asset."
|
|
778
|
+
},
|
|
779
|
+
"signedUrl": {
|
|
780
|
+
"type": "string",
|
|
781
|
+
"format": "uri",
|
|
782
|
+
"description": "The temporary URL for downloading the asset."
|
|
783
|
+
},
|
|
784
|
+
"expiresAt": {
|
|
785
|
+
"type": "string",
|
|
786
|
+
"format": "date-time",
|
|
787
|
+
"description": "When the signed URL expires, in ISO 8601 format."
|
|
788
|
+
}
|
|
789
|
+
},
|
|
790
|
+
"required": [
|
|
791
|
+
"assetId",
|
|
792
|
+
"signedUrl",
|
|
793
|
+
"expiresAt"
|
|
794
|
+
]
|
|
795
|
+
},
|
|
659
796
|
"Feed": {
|
|
660
797
|
"type": "object",
|
|
661
798
|
"properties": {
|
|
@@ -1082,7 +1219,7 @@
|
|
|
1082
1219
|
"/bookmarks/search": {
|
|
1083
1220
|
"get": {
|
|
1084
1221
|
"operationId": "searchBookmarks",
|
|
1085
|
-
"description": "
|
|
1222
|
+
"description": "Search across all bookmarks using full-text, semantic, or hybrid ranking. Full-text search covers bookmark titles, content, descriptions, and notes. Results default to full-text relevance sorting; semantic and hybrid modes support relevance sorting only.",
|
|
1086
1223
|
"summary": "Search bookmarks",
|
|
1087
1224
|
"tags": [
|
|
1088
1225
|
"Bookmarks"
|
|
@@ -1103,6 +1240,22 @@
|
|
|
1103
1240
|
"name": "q",
|
|
1104
1241
|
"in": "query"
|
|
1105
1242
|
},
|
|
1243
|
+
{
|
|
1244
|
+
"schema": {
|
|
1245
|
+
"type": "string",
|
|
1246
|
+
"enum": [
|
|
1247
|
+
"fts",
|
|
1248
|
+
"semantic",
|
|
1249
|
+
"hybrid"
|
|
1250
|
+
],
|
|
1251
|
+
"default": "fts",
|
|
1252
|
+
"description": "Search strategy. 'fts' uses full-text search, 'semantic' uses bookmark embeddings, and 'hybrid' fuses a fixed candidate window from both. Hybrid falls back to full-text search when the query contains no free-text terms or when embedding infrastructure is unavailable. Semantic hits below a minimum similarity are dropped, so semantic search may return fewer results than requested."
|
|
1253
|
+
},
|
|
1254
|
+
"required": false,
|
|
1255
|
+
"description": "Search strategy. 'fts' uses full-text search, 'semantic' uses bookmark embeddings, and 'hybrid' fuses a fixed candidate window from both. Hybrid falls back to full-text search when the query contains no free-text terms or when embedding infrastructure is unavailable. Semantic hits below a minimum similarity are dropped, so semantic search may return fewer results than requested.",
|
|
1256
|
+
"name": "searchMode",
|
|
1257
|
+
"in": "query"
|
|
1258
|
+
},
|
|
1106
1259
|
{
|
|
1107
1260
|
"schema": {
|
|
1108
1261
|
"type": "string",
|
|
@@ -1438,6 +1591,10 @@
|
|
|
1438
1591
|
"id": {
|
|
1439
1592
|
"type": "string"
|
|
1440
1593
|
},
|
|
1594
|
+
"firstCreatedAt": {
|
|
1595
|
+
"type": "string",
|
|
1596
|
+
"format": "date-time"
|
|
1597
|
+
},
|
|
1441
1598
|
"createdAt": {
|
|
1442
1599
|
"type": "string",
|
|
1443
1600
|
"format": "date-time"
|
|
@@ -1477,6 +1634,16 @@
|
|
|
1477
1634
|
null
|
|
1478
1635
|
]
|
|
1479
1636
|
},
|
|
1637
|
+
"embeddingStatus": {
|
|
1638
|
+
"type": "string",
|
|
1639
|
+
"nullable": true,
|
|
1640
|
+
"enum": [
|
|
1641
|
+
"success",
|
|
1642
|
+
"failure",
|
|
1643
|
+
"pending",
|
|
1644
|
+
null
|
|
1645
|
+
]
|
|
1646
|
+
},
|
|
1480
1647
|
"note": {
|
|
1481
1648
|
"type": "string",
|
|
1482
1649
|
"nullable": true
|
|
@@ -1512,6 +1679,7 @@
|
|
|
1512
1679
|
"favourited",
|
|
1513
1680
|
"taggingStatus",
|
|
1514
1681
|
"summarizationStatus",
|
|
1682
|
+
"embeddingStatus",
|
|
1515
1683
|
"userId"
|
|
1516
1684
|
]
|
|
1517
1685
|
}
|
|
@@ -1542,6 +1710,116 @@
|
|
|
1542
1710
|
}
|
|
1543
1711
|
}
|
|
1544
1712
|
},
|
|
1713
|
+
"/bookmarks/{bookmarkId}/content": {
|
|
1714
|
+
"get": {
|
|
1715
|
+
"operationId": "getBookmarkReadableContent",
|
|
1716
|
+
"description": "Retrieve a bounded chunk of an agent-readable bookmark representation. Link content is rendered from extracted HTML; text and media bookmarks use their stored or extracted text. Continue reading by passing the opaque `nextCursor` from the previous response.",
|
|
1717
|
+
"summary": "Get readable bookmark content",
|
|
1718
|
+
"tags": [
|
|
1719
|
+
"Bookmarks"
|
|
1720
|
+
],
|
|
1721
|
+
"security": [
|
|
1722
|
+
{
|
|
1723
|
+
"bearerAuth": []
|
|
1724
|
+
}
|
|
1725
|
+
],
|
|
1726
|
+
"parameters": [
|
|
1727
|
+
{
|
|
1728
|
+
"$ref": "#/components/parameters/BookmarkId"
|
|
1729
|
+
},
|
|
1730
|
+
{
|
|
1731
|
+
"schema": {
|
|
1732
|
+
"type": "string",
|
|
1733
|
+
"enum": [
|
|
1734
|
+
"markdown",
|
|
1735
|
+
"text"
|
|
1736
|
+
],
|
|
1737
|
+
"description": "The readable representation. If omitted with a cursor, the cursor's format is used; otherwise defaults to markdown."
|
|
1738
|
+
},
|
|
1739
|
+
"required": false,
|
|
1740
|
+
"description": "The readable representation. If omitted with a cursor, the cursor's format is used; otherwise defaults to markdown.",
|
|
1741
|
+
"name": "format",
|
|
1742
|
+
"in": "query"
|
|
1743
|
+
},
|
|
1744
|
+
{
|
|
1745
|
+
"schema": {
|
|
1746
|
+
"type": "integer",
|
|
1747
|
+
"minimum": 1,
|
|
1748
|
+
"maximum": 50000,
|
|
1749
|
+
"default": 12000,
|
|
1750
|
+
"description": "Maximum number of Unicode characters to return. The chunk may end earlier at a paragraph or line boundary."
|
|
1751
|
+
},
|
|
1752
|
+
"required": false,
|
|
1753
|
+
"description": "Maximum number of Unicode characters to return. The chunk may end earlier at a paragraph or line boundary.",
|
|
1754
|
+
"name": "maxChars",
|
|
1755
|
+
"in": "query"
|
|
1756
|
+
},
|
|
1757
|
+
{
|
|
1758
|
+
"schema": {
|
|
1759
|
+
"type": "string",
|
|
1760
|
+
"description": "Opaque continuation cursor returned as `nextCursor` by a previous response."
|
|
1761
|
+
},
|
|
1762
|
+
"required": false,
|
|
1763
|
+
"description": "Opaque continuation cursor returned as `nextCursor` by a previous response.",
|
|
1764
|
+
"name": "cursor",
|
|
1765
|
+
"in": "query"
|
|
1766
|
+
}
|
|
1767
|
+
],
|
|
1768
|
+
"responses": {
|
|
1769
|
+
"200": {
|
|
1770
|
+
"description": "A bounded chunk of readable bookmark content.",
|
|
1771
|
+
"content": {
|
|
1772
|
+
"application/json": {
|
|
1773
|
+
"schema": {
|
|
1774
|
+
"$ref": "#/components/schemas/BookmarkReadableContent"
|
|
1775
|
+
}
|
|
1776
|
+
}
|
|
1777
|
+
}
|
|
1778
|
+
},
|
|
1779
|
+
"400": {
|
|
1780
|
+
"description": "Bad request — the cursor is malformed, mismatched, or outside the content.",
|
|
1781
|
+
"content": {
|
|
1782
|
+
"application/json": {
|
|
1783
|
+
"schema": {
|
|
1784
|
+
"$ref": "#/components/schemas/Error"
|
|
1785
|
+
}
|
|
1786
|
+
}
|
|
1787
|
+
}
|
|
1788
|
+
},
|
|
1789
|
+
"401": {
|
|
1790
|
+
"description": "Unauthorized — the Bearer token is missing, invalid, or expired.",
|
|
1791
|
+
"content": {
|
|
1792
|
+
"text/plain": {
|
|
1793
|
+
"schema": {
|
|
1794
|
+
"type": "string",
|
|
1795
|
+
"example": "Unauthorized"
|
|
1796
|
+
}
|
|
1797
|
+
}
|
|
1798
|
+
}
|
|
1799
|
+
},
|
|
1800
|
+
"404": {
|
|
1801
|
+
"description": "Bookmark not found.",
|
|
1802
|
+
"content": {
|
|
1803
|
+
"application/json": {
|
|
1804
|
+
"schema": {
|
|
1805
|
+
"$ref": "#/components/schemas/Error"
|
|
1806
|
+
}
|
|
1807
|
+
}
|
|
1808
|
+
}
|
|
1809
|
+
},
|
|
1810
|
+
"409": {
|
|
1811
|
+
"description": "The bookmark content changed after the supplied cursor was issued.",
|
|
1812
|
+
"content": {
|
|
1813
|
+
"application/json": {
|
|
1814
|
+
"schema": {
|
|
1815
|
+
"$ref": "#/components/schemas/Error"
|
|
1816
|
+
}
|
|
1817
|
+
}
|
|
1818
|
+
}
|
|
1819
|
+
}
|
|
1820
|
+
}
|
|
1821
|
+
}
|
|
1822
|
+
},
|
|
1545
1823
|
"/bookmarks/{bookmarkId}/summarize": {
|
|
1546
1824
|
"post": {
|
|
1547
1825
|
"operationId": "summarizeBookmark",
|
|
@@ -1571,6 +1849,10 @@
|
|
|
1571
1849
|
"id": {
|
|
1572
1850
|
"type": "string"
|
|
1573
1851
|
},
|
|
1852
|
+
"firstCreatedAt": {
|
|
1853
|
+
"type": "string",
|
|
1854
|
+
"format": "date-time"
|
|
1855
|
+
},
|
|
1574
1856
|
"createdAt": {
|
|
1575
1857
|
"type": "string",
|
|
1576
1858
|
"format": "date-time"
|
|
@@ -1610,6 +1892,16 @@
|
|
|
1610
1892
|
null
|
|
1611
1893
|
]
|
|
1612
1894
|
},
|
|
1895
|
+
"embeddingStatus": {
|
|
1896
|
+
"type": "string",
|
|
1897
|
+
"nullable": true,
|
|
1898
|
+
"enum": [
|
|
1899
|
+
"success",
|
|
1900
|
+
"failure",
|
|
1901
|
+
"pending",
|
|
1902
|
+
null
|
|
1903
|
+
]
|
|
1904
|
+
},
|
|
1613
1905
|
"note": {
|
|
1614
1906
|
"type": "string",
|
|
1615
1907
|
"nullable": true
|
|
@@ -1645,6 +1937,7 @@
|
|
|
1645
1937
|
"favourited",
|
|
1646
1938
|
"taggingStatus",
|
|
1647
1939
|
"summarizationStatus",
|
|
1940
|
+
"embeddingStatus",
|
|
1648
1941
|
"userId"
|
|
1649
1942
|
]
|
|
1650
1943
|
}
|
|
@@ -2827,8 +3120,8 @@
|
|
|
2827
3120
|
},
|
|
2828
3121
|
{
|
|
2829
3122
|
"schema": {
|
|
2830
|
-
"type": "
|
|
2831
|
-
"
|
|
3123
|
+
"type": "integer",
|
|
3124
|
+
"minimum": 1
|
|
2832
3125
|
},
|
|
2833
3126
|
"required": false,
|
|
2834
3127
|
"name": "limit",
|
|
@@ -3955,6 +4248,49 @@
|
|
|
3955
4248
|
}
|
|
3956
4249
|
}
|
|
3957
4250
|
},
|
|
4251
|
+
"/assets/{assetId}/signed-url": {
|
|
4252
|
+
"get": {
|
|
4253
|
+
"operationId": "getAssetSignedUrl",
|
|
4254
|
+
"description": "Generate a temporary signed URL that can be used to download an asset without sending an API key.",
|
|
4255
|
+
"summary": "Get a signed asset URL",
|
|
4256
|
+
"tags": [
|
|
4257
|
+
"Assets"
|
|
4258
|
+
],
|
|
4259
|
+
"security": [
|
|
4260
|
+
{
|
|
4261
|
+
"bearerAuth": []
|
|
4262
|
+
}
|
|
4263
|
+
],
|
|
4264
|
+
"parameters": [
|
|
4265
|
+
{
|
|
4266
|
+
"$ref": "#/components/parameters/AssetId"
|
|
4267
|
+
}
|
|
4268
|
+
],
|
|
4269
|
+
"responses": {
|
|
4270
|
+
"200": {
|
|
4271
|
+
"description": "A temporary signed URL for downloading the asset and its expiration time.",
|
|
4272
|
+
"content": {
|
|
4273
|
+
"application/json": {
|
|
4274
|
+
"schema": {
|
|
4275
|
+
"$ref": "#/components/schemas/SignedAssetUrl"
|
|
4276
|
+
}
|
|
4277
|
+
}
|
|
4278
|
+
}
|
|
4279
|
+
},
|
|
4280
|
+
"401": {
|
|
4281
|
+
"description": "Unauthorized — the Bearer token is missing, invalid, or expired.",
|
|
4282
|
+
"content": {
|
|
4283
|
+
"text/plain": {
|
|
4284
|
+
"schema": {
|
|
4285
|
+
"type": "string",
|
|
4286
|
+
"example": "Unauthorized"
|
|
4287
|
+
}
|
|
4288
|
+
}
|
|
4289
|
+
}
|
|
4290
|
+
}
|
|
4291
|
+
}
|
|
4292
|
+
}
|
|
4293
|
+
},
|
|
3958
4294
|
"/admin/users/{userId}": {
|
|
3959
4295
|
"put": {
|
|
3960
4296
|
"operationId": "adminUpdateUser",
|
|
@@ -4087,7 +4423,7 @@
|
|
|
4087
4423
|
"/admin/jobs/trigger/recrawl": {
|
|
4088
4424
|
"post": {
|
|
4089
4425
|
"operationId": "adminTriggerRecrawl",
|
|
4090
|
-
"description": "Trigger a recrawl of link bookmarks. You can filter by crawl status to target specific bookmarks (e.g., only failed ones). Optionally run AI inference after crawling. Requires admin role.",
|
|
4426
|
+
"description": "Trigger a recrawl of link bookmarks. You can filter by crawl status to target specific bookmarks (e.g., only failed ones) and by how recently they were modified. Optionally run AI inference after crawling. Requires admin role.",
|
|
4091
4427
|
"summary": "Trigger recrawl of links (admin)",
|
|
4092
4428
|
"tags": [
|
|
4093
4429
|
"Admin"
|
|
@@ -4119,11 +4455,18 @@
|
|
|
4119
4455
|
"type": "boolean",
|
|
4120
4456
|
"default": false,
|
|
4121
4457
|
"description": "Whether to run AI inference after crawling."
|
|
4458
|
+
},
|
|
4459
|
+
"modifiedWithinSeconds": {
|
|
4460
|
+
"type": "integer",
|
|
4461
|
+
"minimum": 0,
|
|
4462
|
+
"exclusiveMinimum": true,
|
|
4463
|
+
"description": "Only process bookmarks modified within this many seconds. Omit to process all matching bookmarks."
|
|
4122
4464
|
}
|
|
4123
4465
|
},
|
|
4124
4466
|
"example": {
|
|
4125
4467
|
"crawlStatus": "failure",
|
|
4126
|
-
"runInference": false
|
|
4468
|
+
"runInference": false,
|
|
4469
|
+
"modifiedWithinSeconds": 3600
|
|
4127
4470
|
}
|
|
4128
4471
|
}
|
|
4129
4472
|
}
|
|
@@ -4186,7 +4529,7 @@
|
|
|
4186
4529
|
"/admin/jobs/trigger/reindex": {
|
|
4187
4530
|
"post": {
|
|
4188
4531
|
"operationId": "adminTriggerReindex",
|
|
4189
|
-
"description": "Trigger a reindex of
|
|
4532
|
+
"description": "Trigger a reindex of bookmarks in the search engine. Without modifiedWithinSeconds, this clears the existing index and re-queues all bookmarks. When set, only bookmarks modified within that many seconds are re-queued and the existing index is preserved. Requires admin role.",
|
|
4190
4533
|
"summary": "Trigger reindex of all bookmarks (admin)",
|
|
4191
4534
|
"tags": [
|
|
4192
4535
|
"Admin"
|
|
@@ -4196,6 +4539,27 @@
|
|
|
4196
4539
|
"bearerAuth": []
|
|
4197
4540
|
}
|
|
4198
4541
|
],
|
|
4542
|
+
"requestBody": {
|
|
4543
|
+
"description": "Optional time window for the reindex job.",
|
|
4544
|
+
"content": {
|
|
4545
|
+
"application/json": {
|
|
4546
|
+
"schema": {
|
|
4547
|
+
"type": "object",
|
|
4548
|
+
"properties": {
|
|
4549
|
+
"modifiedWithinSeconds": {
|
|
4550
|
+
"type": "integer",
|
|
4551
|
+
"minimum": 0,
|
|
4552
|
+
"exclusiveMinimum": true,
|
|
4553
|
+
"description": "Only process bookmarks modified within this many seconds. Omit to process all matching bookmarks."
|
|
4554
|
+
}
|
|
4555
|
+
},
|
|
4556
|
+
"example": {
|
|
4557
|
+
"modifiedWithinSeconds": 3600
|
|
4558
|
+
}
|
|
4559
|
+
}
|
|
4560
|
+
}
|
|
4561
|
+
}
|
|
4562
|
+
},
|
|
4199
4563
|
"responses": {
|
|
4200
4564
|
"200": {
|
|
4201
4565
|
"description": "Reindex jobs triggered successfully.",
|
|
@@ -4243,7 +4607,7 @@
|
|
|
4243
4607
|
"/admin/jobs/trigger/inference": {
|
|
4244
4608
|
"post": {
|
|
4245
4609
|
"operationId": "adminTriggerInference",
|
|
4246
|
-
"description": "Trigger AI inference (tagging or summarization) on bookmarks. You can filter by status
|
|
4610
|
+
"description": "Trigger AI inference (tagging or summarization) on bookmarks. You can filter by status and by how recently bookmarks were modified. Requires admin role.",
|
|
4247
4611
|
"summary": "Trigger AI inference on bookmarks (admin)",
|
|
4248
4612
|
"tags": [
|
|
4249
4613
|
"Admin"
|
|
@@ -4279,6 +4643,12 @@
|
|
|
4279
4643
|
],
|
|
4280
4644
|
"default": "all",
|
|
4281
4645
|
"description": "Filter bookmarks by their inference status. Use 'failure' to retry only failed ones."
|
|
4646
|
+
},
|
|
4647
|
+
"modifiedWithinSeconds": {
|
|
4648
|
+
"type": "integer",
|
|
4649
|
+
"minimum": 0,
|
|
4650
|
+
"exclusiveMinimum": true,
|
|
4651
|
+
"description": "Only process bookmarks modified within this many seconds. Omit to process all matching bookmarks."
|
|
4282
4652
|
}
|
|
4283
4653
|
},
|
|
4284
4654
|
"required": [
|
|
@@ -4286,7 +4656,8 @@
|
|
|
4286
4656
|
],
|
|
4287
4657
|
"example": {
|
|
4288
4658
|
"type": "tag",
|
|
4289
|
-
"status": "failure"
|
|
4659
|
+
"status": "failure",
|
|
4660
|
+
"modifiedWithinSeconds": 3600
|
|
4290
4661
|
}
|
|
4291
4662
|
}
|
|
4292
4663
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: karakeep_python_api
|
|
3
|
-
Version: 1.
|
|
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).*
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
karakeep_python_api/__init__.py,sha256=qk3MeIIvnCNAyYzJrv8dMKVXvA4ejLU3mhB3xFzdLDY,606
|
|
2
|
+
karakeep_python_api/__main__.py,sha256=weIwZtSEe8rbSd1nnVj-F__e84tBsVZTaR6DGdZFhn4,39410
|
|
3
|
+
karakeep_python_api/datatypes.py,sha256=tOROux_Ehnum0hmbopFfYBZ_ZaB8M22ktPXWtnOP8ig,6936
|
|
4
|
+
karakeep_python_api/karakeep_api.py,sha256=ExS7S8CjyNYF56G-TitRPlQewyx-Q5rRBkhrbm3-ukk,126407
|
|
5
|
+
karakeep_python_api/openapi_reference.json,sha256=uENNNF1bHCuHzJPHQa2-DfqlEOBrLmQ0mFrVnPu9XaA,163271
|
|
6
|
+
karakeep_python_api-1.9.0.dist-info/licenses/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
|
|
7
|
+
karakeep_python_api-1.9.0.dist-info/METADATA,sha256=P9j-caj1OfqFGsnIGvwpKlRVvYrUd6_w37wACZ_v_pE,17687
|
|
8
|
+
karakeep_python_api-1.9.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
9
|
+
karakeep_python_api-1.9.0.dist-info/entry_points.txt,sha256=n0leQp_IX2NivoWuUcaR9ZHwAvl_6yt-NcHWuCJyxNo,62
|
|
10
|
+
karakeep_python_api-1.9.0.dist-info/top_level.txt,sha256=X3VKqh9YAbPQp144db0Ko2C5Q2y6-nwpPgtnuCiSDmU,20
|
|
11
|
+
karakeep_python_api-1.9.0.dist-info/RECORD,,
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
karakeep_python_api/__init__.py,sha256=qk3MeIIvnCNAyYzJrv8dMKVXvA4ejLU3mhB3xFzdLDY,606
|
|
2
|
-
karakeep_python_api/__main__.py,sha256=4337OITOcfW5Mze-aqQgb_EBR_WznScRTIIfIvHQ2co,38444
|
|
3
|
-
karakeep_python_api/datatypes.py,sha256=uKhjm7uQQnh-PgsLPl0atBt_ucQBIi0PV2SWFcCNXdg,4850
|
|
4
|
-
karakeep_python_api/karakeep_api.py,sha256=sdyjcz_srsp2guBoCmaXLljsmKmG1pqZVAGuZb82zQQ,117262
|
|
5
|
-
karakeep_python_api/openapi_reference.json,sha256=abhe0s2_sJBL0EyD3T09JLRIOIFevSAx0K2Jucx_fyQ,150304
|
|
6
|
-
karakeep_python_api-1.8.0.dist-info/licenses/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
|
|
7
|
-
karakeep_python_api-1.8.0.dist-info/METADATA,sha256=VFNuHpdhWePYCRn9h-gc_NBxMX58Em4Pf5EMPxgTX_Y,17053
|
|
8
|
-
karakeep_python_api-1.8.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
9
|
-
karakeep_python_api-1.8.0.dist-info/entry_points.txt,sha256=n0leQp_IX2NivoWuUcaR9ZHwAvl_6yt-NcHWuCJyxNo,62
|
|
10
|
-
karakeep_python_api-1.8.0.dist-info/top_level.txt,sha256=X3VKqh9YAbPQp144db0Ko2C5Q2y6-nwpPgtnuCiSDmU,20
|
|
11
|
-
karakeep_python_api-1.8.0.dist-info/RECORD,,
|
{karakeep_python_api-1.8.0.dist-info → karakeep_python_api-1.9.0.dist-info}/entry_points.txt
RENAMED
|
File without changes
|
{karakeep_python_api-1.8.0.dist-info → karakeep_python_api-1.9.0.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|
|
File without changes
|