doc-store-client-dev 0.1.185__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.
@@ -0,0 +1,194 @@
1
+ """Public API for the transport-neutral doc-store client package."""
2
+
3
+ from importlib.metadata import PackageNotFoundError as _PackageNotFoundError
4
+ from importlib.metadata import version as _distribution_version
5
+ from pathlib import Path as _Path
6
+ import tomllib as _tomllib
7
+
8
+ from .client import (
9
+ DOC_STORE_COMMANDS,
10
+ DocStoreClient,
11
+ DocStoreClientError,
12
+ DocStoreNotFoundError,
13
+ FileAlreadyLockedError,
14
+ LockServiceUnavailableError,
15
+ SessionNotFoundError,
16
+ )
17
+ from .owned_document_cleanup import OwnedDocumentCleanup, OwnedDocumentCleanupError
18
+ from .text_verification import text_verification_phrase
19
+ from .models import (
20
+ BackupEmergencyResult,
21
+ BackupInspectFile,
22
+ BackupInspectResult,
23
+ BackupPoint,
24
+ BackupPointsResult,
25
+ BackupRecoverCatalogResult,
26
+ BackupRestoreResult,
27
+ BackupRunResult,
28
+ BackupStatusResult,
29
+ ChapterGetRequest,
30
+ ChapterGetResult,
31
+ ChapterTextGetRequest,
32
+ ChunkHistoryRequest,
33
+ ChunkHistoryResult,
34
+ ChunkVersionAddRequest,
35
+ ChunkVersionAddResult,
36
+ ChunkVersionDeleteRequest,
37
+ ChunkVersionDeleteResult,
38
+ ChunkVersionDiffRequest,
39
+ ChunkVersionDiffResult,
40
+ ChunkVersionGetRequest,
41
+ ChunkVersionGetResult,
42
+ ChunkVersionItem,
43
+ ChunkVersionListRequest,
44
+ ChunkVersionListResult,
45
+ ChunkVersionRestoreRequest,
46
+ ChunkVersionRestoreResult,
47
+ ChunkVersionRetireRequest,
48
+ ChunkVersionRetireResult,
49
+ ChunkVersionSetCurrentRequest,
50
+ ChunkVersionSetCurrentResult,
51
+ ChunkVersionTextMutationRequest,
52
+ ChunkVersionUpdateRequest,
53
+ ChunkVersionUpdateResult,
54
+ DocumentChunkRequest,
55
+ DocumentChunkResult,
56
+ DocumentCreateRequest,
57
+ DocumentCreateResult,
58
+ DocumentDeleteRequest,
59
+ DocumentDeleteResult,
60
+ DocumentGetRequest,
61
+ DocumentGetResult,
62
+ DocumentRebindRequest,
63
+ DocumentRebindResult,
64
+ DocumentUpdateRequest,
65
+ DocumentUpdateResult,
66
+ DocumentWriteRequest,
67
+ DocumentWriteResult,
68
+ EntityGetRequest,
69
+ EntityGetResult,
70
+ EntityTextGetRequest,
71
+ EntityTextGetResult,
72
+ EntityIdsRequest,
73
+ EntityLifecycleResult,
74
+ EntityListRequest,
75
+ EntityListResult,
76
+ EntityOwnerTreeRequest,
77
+ EntityOwnerTreeResult,
78
+ EntityReferencesRequest,
79
+ EntityReferencesResult,
80
+ OperationState,
81
+ ParagraphGetByNumberRequest,
82
+ ParagraphGetByNumberResult,
83
+ ParagraphGetRequest,
84
+ ParagraphGetResult,
85
+ ProcessingStatusRequest,
86
+ ProcessingStatusResult,
87
+ RankedSearchHit,
88
+ RetrievalRequest,
89
+ RetrievalResult,
90
+ SearchResult,
91
+ ServerError,
92
+ SemanticChunkMetadataUpdateRequest,
93
+ SemanticChunkMetadataUpdateResult,
94
+ SourceFileReconstructRequest,
95
+ TextReconstructionRequest,
96
+ TextReconstructionResult,
97
+ )
98
+
99
+ try:
100
+ __version__ = _distribution_version("doc-store-client")
101
+ except _PackageNotFoundError:
102
+ _pyproject = _Path(__file__).resolve().parents[2] / "pyproject.toml"
103
+ __version__ = _tomllib.loads(_pyproject.read_text(encoding="utf-8"))["project"]["version"]
104
+
105
+ # The package includes ``py.typed`` in its distribution metadata.
106
+ __all__ = [
107
+ "BackupEmergencyResult",
108
+ "BackupInspectFile",
109
+ "BackupInspectResult",
110
+ "BackupPoint",
111
+ "BackupPointsResult",
112
+ "BackupRecoverCatalogResult",
113
+ "BackupRestoreResult",
114
+ "BackupRunResult",
115
+ "BackupStatusResult",
116
+ "ChapterGetRequest",
117
+ "ChapterGetResult",
118
+ "ChapterTextGetRequest",
119
+ "ChunkHistoryRequest",
120
+ "ChunkHistoryResult",
121
+ "ChunkVersionAddRequest",
122
+ "ChunkVersionAddResult",
123
+ "ChunkVersionDeleteRequest",
124
+ "ChunkVersionDeleteResult",
125
+ "ChunkVersionDiffRequest",
126
+ "ChunkVersionDiffResult",
127
+ "ChunkVersionGetRequest",
128
+ "ChunkVersionGetResult",
129
+ "ChunkVersionItem",
130
+ "ChunkVersionListRequest",
131
+ "ChunkVersionListResult",
132
+ "ChunkVersionRestoreRequest",
133
+ "ChunkVersionRestoreResult",
134
+ "ChunkVersionRetireRequest",
135
+ "ChunkVersionRetireResult",
136
+ "ChunkVersionSetCurrentRequest",
137
+ "ChunkVersionSetCurrentResult",
138
+ "ChunkVersionTextMutationRequest",
139
+ "ChunkVersionUpdateRequest",
140
+ "ChunkVersionUpdateResult",
141
+ "DOC_STORE_COMMANDS",
142
+ "DocStoreClient",
143
+ "DocStoreClientError",
144
+ "DocStoreNotFoundError",
145
+ "FileAlreadyLockedError",
146
+ "LockServiceUnavailableError",
147
+ "SessionNotFoundError",
148
+ "OwnedDocumentCleanup",
149
+ "OwnedDocumentCleanupError",
150
+ "DocumentCreateRequest",
151
+ "DocumentCreateResult",
152
+ "DocumentChunkRequest",
153
+ "DocumentChunkResult",
154
+ "DocumentDeleteRequest",
155
+ "DocumentDeleteResult",
156
+ "DocumentGetRequest",
157
+ "DocumentGetResult",
158
+ "DocumentRebindRequest",
159
+ "DocumentRebindResult",
160
+ "DocumentUpdateRequest",
161
+ "DocumentUpdateResult",
162
+ "DocumentWriteRequest",
163
+ "DocumentWriteResult",
164
+ "EntityGetRequest",
165
+ "EntityGetResult",
166
+ "EntityTextGetRequest",
167
+ "EntityTextGetResult",
168
+ "EntityIdsRequest",
169
+ "EntityLifecycleResult",
170
+ "EntityListRequest",
171
+ "EntityListResult",
172
+ "EntityOwnerTreeRequest",
173
+ "EntityOwnerTreeResult",
174
+ "EntityReferencesRequest",
175
+ "EntityReferencesResult",
176
+ "OperationState",
177
+ "ParagraphGetByNumberRequest",
178
+ "ParagraphGetByNumberResult",
179
+ "ParagraphGetRequest",
180
+ "ParagraphGetResult",
181
+ "ProcessingStatusRequest",
182
+ "ProcessingStatusResult",
183
+ "RankedSearchHit",
184
+ "RetrievalRequest",
185
+ "RetrievalResult",
186
+ "SearchResult",
187
+ "ServerError",
188
+ "SemanticChunkMetadataUpdateRequest",
189
+ "SemanticChunkMetadataUpdateResult",
190
+ "SourceFileReconstructRequest",
191
+ "TextReconstructionRequest",
192
+ "TextReconstructionResult",
193
+ "text_verification_phrase",
194
+ ]
@@ -0,0 +1,192 @@
1
+ """Command line entrypoint for the installed doc-store client."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ import asyncio
7
+ import json
8
+ import os
9
+ from pathlib import Path
10
+ from typing import Any
11
+ from urllib.parse import urlsplit
12
+
13
+
14
+ class _AdapterBridge:
15
+ def __init__(self, client: Any) -> None:
16
+ self._client = client
17
+
18
+ async def execute_command_unified(
19
+ self, command: str, params: dict[str, Any], **kwargs: Any
20
+ ) -> Any:
21
+ dispatch = getattr(self._client, "execute_command_unified", None)
22
+ if dispatch is None:
23
+ dispatch = getattr(self._client, "execute_command", None)
24
+ if dispatch is None:
25
+ raise TypeError("configured adapter exposes no supported command dispatch method")
26
+ result = await dispatch(command, params, **kwargs)
27
+ if isinstance(result, dict) and "error" in result:
28
+ return {
29
+ "success": False,
30
+ "code": "SERVER_ERROR",
31
+ "message": str(result["error"]),
32
+ "details": {},
33
+ }
34
+ return result
35
+
36
+ async def wait_for_job(self, job_id: str, **kwargs: Any) -> Any:
37
+ return await self._client.wait_for_job(job_id, **kwargs)
38
+
39
+ async def fetch_command_session_result(self, job_id: str) -> Any:
40
+ return await self._client.fetch_command_session_result(job_id)
41
+
42
+
43
+ def _config_path(explicit: str | None) -> Path | None:
44
+ if explicit:
45
+ return Path(explicit).expanduser()
46
+ configured = os.environ.get("DOC_STORE_CLIENT_CONFIG")
47
+ if configured:
48
+ return Path(configured).expanduser()
49
+ current = Path.cwd().resolve()
50
+ for directory in (current, *current.parents):
51
+ candidate = directory / "doc-store-client.json"
52
+ if candidate.is_file():
53
+ return candidate
54
+ return None
55
+
56
+
57
+ def _load_config(args: argparse.Namespace) -> dict[str, Any]:
58
+ path = _config_path(args.config)
59
+ config: dict[str, Any] = {}
60
+ if path is not None:
61
+ try:
62
+ value = json.loads(path.read_text(encoding="utf-8"))
63
+ except (OSError, json.JSONDecodeError) as exc:
64
+ raise ValueError(f"Unable to load configuration: {exc}") from exc
65
+ if not isinstance(value, dict):
66
+ raise ValueError("Configuration must be a JSON object")
67
+ config = value
68
+ if args.server_url:
69
+ config["server_url"] = args.server_url
70
+ elif os.environ.get("DOC_STORE_SERVER_URL"):
71
+ config.setdefault("server_url", os.environ["DOC_STORE_SERVER_URL"])
72
+ if not config.get("server_url"):
73
+ raise ValueError(
74
+ "No server URL configured; use --config, --server-url, "
75
+ "DOC_STORE_CLIENT_CONFIG, or DOC_STORE_SERVER_URL"
76
+ )
77
+ return config
78
+
79
+
80
+ def _params(text: str | None) -> dict[str, Any]:
81
+ if text is None:
82
+ return {}
83
+ try:
84
+ value = json.loads(text)
85
+ except json.JSONDecodeError as exc:
86
+ raise ValueError(f"--params must be a JSON object: {exc.msg}") from exc
87
+ if not isinstance(value, dict):
88
+ raise ValueError("--params must be a JSON object")
89
+ return value
90
+
91
+
92
+ async def _execute(args: argparse.Namespace) -> Any:
93
+ from mcp_proxy_adapter.client.jsonrpc_client import JsonRpcClient
94
+
95
+ from doc_store_client.client import DocStoreClient
96
+
97
+ config = _load_config(args)
98
+ parsed = urlsplit(str(config["server_url"]))
99
+ if not parsed.hostname:
100
+ raise ValueError("server_url must include a host")
101
+ protocol = str(config.get("protocol") or parsed.scheme or "http")
102
+ port = int(
103
+ config.get("port")
104
+ or parsed.port
105
+ or (443 if protocol in {"https", "mtls"} else 80)
106
+ )
107
+ transport = JsonRpcClient(
108
+ protocol=protocol,
109
+ host=str(config.get("host") or parsed.hostname),
110
+ port=port,
111
+ token_header=config.get("token_header"),
112
+ token=config.get("token"),
113
+ cert=config.get("cert"),
114
+ key=config.get("key"),
115
+ ca=config.get("ca"),
116
+ check_hostname=config.get("check_hostname"),
117
+ timeout=float(config["timeout"]) if config.get("timeout") is not None else None,
118
+ )
119
+
120
+ async def emit_event(event: dict[str, Any]) -> None:
121
+ print(
122
+ json.dumps(event, ensure_ascii=False, separators=(",", ":")),
123
+ file=os.sys.stderr,
124
+ flush=True,
125
+ )
126
+
127
+ client = DocStoreClient(_AdapterBridge(transport), event_callback=emit_event)
128
+ try:
129
+ if args.action == "call":
130
+ return await client.call(args.command, _params(args.params))
131
+ params = _params(args.params)
132
+ if args.file:
133
+ path = Path(args.file)
134
+ try:
135
+ payload = path.read_text(encoding="utf-8")
136
+ except OSError as exc:
137
+ raise ValueError(f"Unable to read --file: {exc}") from exc
138
+ params["raw_text"] = payload
139
+ return await client.call(args.action, params)
140
+ finally:
141
+ await transport.close()
142
+
143
+
144
+ def _parser() -> argparse.ArgumentParser:
145
+ parser = argparse.ArgumentParser(
146
+ prog="doc-store-client",
147
+ description="Execute doc-store server commands through the installed client.",
148
+ )
149
+ parser.add_argument("--config", help="JSON config path; defaults to nearest doc-store-client.json")
150
+ parser.add_argument("--server-url", help="Override the configured server URL")
151
+ sub = parser.add_subparsers(dest="action", required=True)
152
+ call = sub.add_parser("call", help="Call any server command with a JSON object")
153
+ call.add_argument("command", help="Server command name")
154
+ call.add_argument("--params", help="JSON object passed to the command")
155
+ for name in ("document-create", "document-update", "import"):
156
+ command = sub.add_parser(name, help=f"Run {name} through the client")
157
+ command.set_defaults(action={"document-create": "document_create", "document-update": "document_update", "import": "document_import"}[name])
158
+ command.add_argument("--params", help="JSON object passed to the command")
159
+ command.add_argument("--file", help="UTF-8 text file to use as the document source")
160
+ return parser
161
+
162
+
163
+ def main() -> int:
164
+ args = _parser().parse_args()
165
+ try:
166
+ result = asyncio.run(_execute(args))
167
+ except Exception as exc:
168
+ message = str(exc)
169
+ lowered = message.lower()
170
+ code = "CLI_ERROR"
171
+ details: Any = {}
172
+ server_error = getattr(exc, "error", None)
173
+ if server_error is not None:
174
+ code = str(getattr(server_error, "code", "SERVER_ERROR"))
175
+ message = str(getattr(server_error, "message", message))
176
+ details = getattr(server_error, "details", {}) or {}
177
+ if "no module named" in lowered:
178
+ code = "CLIENT_RUNTIME_INCOMPATIBLE"
179
+ print(
180
+ json.dumps(
181
+ {"code": code, "message": message, "details": details},
182
+ ensure_ascii=False,
183
+ ),
184
+ file=os.sys.stderr,
185
+ )
186
+ return 2
187
+ print(json.dumps(result, ensure_ascii=False, indent=2, default=str))
188
+ return 0
189
+
190
+
191
+ if __name__ == "__main__":
192
+ raise SystemExit(main())