deepquery-sdk 1.0.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.
@@ -0,0 +1,74 @@
1
+ """__CONNECTOR_TITLE__ connector for Deep Query, built with DeepQuerySDK.
2
+
3
+ Fill in the auth endpoints, the resource fetch, and the action preview/execute
4
+ with real calls to your system. Run `deepquery validate <this file>` to check the
5
+ safety contracts, and `deepquery run-dev <this file>` to exercise it locally.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from deepquery_sdk import Connector, OAuth2Auth, action, resource
11
+
12
+
13
+ class __CLASS_NAME__(Connector):
14
+ name = "__CONNECTOR_NAME__"
15
+ version = "0.1.0"
16
+ description = "TODO: one line describing what this connector reads and does."
17
+
18
+ # Declare how the connector authenticates. Swap for ApiKeyAuth / BasicAuth /
19
+ # MTLSAuth as needed, and request the *minimum* scopes (§13). The gateway runs
20
+ # and stores the grant; this connector never stores credentials.
21
+ auth = OAuth2Auth(
22
+ authorize_endpoint="https://example.com/oauth/authorize",
23
+ token_endpoint="https://example.com/oauth/token",
24
+ scopes=["read"],
25
+ )
26
+ requires_network = True
27
+ air_gapped_capable = False
28
+
29
+ # -- a read (resource): returns citeable records ----------------------
30
+ @resource(
31
+ description="TODO: describe what this read returns and when to use it.",
32
+ input_schema={
33
+ "type": "object",
34
+ "properties": {"query": {"type": "string", "description": "Search text."}},
35
+ "required": ["query"],
36
+ },
37
+ )
38
+ def search(self, query: str):
39
+ # TODO: call your system's read API. Wrap each record with self.cite(...)
40
+ # so it carries a provenance envelope (§6).
41
+ return [
42
+ self.cite(
43
+ {"id": "EXAMPLE-1", "title": f"Result for {query}"},
44
+ source_object_id="EXAMPLE-1",
45
+ title_or_label=f"EXAMPLE-1 — Result for {query}",
46
+ deep_link="https://example.com/objects/EXAMPLE-1",
47
+ mutability_note="live data — may change after retrieval",
48
+ )
49
+ ]
50
+
51
+ # -- an action: gated behind preview -> approve -> execute ------------
52
+ @action(
53
+ description="TODO: describe what this action changes.",
54
+ input_schema={
55
+ "type": "object",
56
+ "properties": {"target": {"type": "string"}, "value": {"type": "string"}},
57
+ "required": ["target", "value"],
58
+ },
59
+ )
60
+ def do_thing(self, target: str, value: str):
61
+ # Only ever called after the approval gate confirms the preview.
62
+ auth = self.apply_auth() # headers built from the injected credential
63
+ return {"updated": target, "value": value}
64
+
65
+ @do_thing.preview
66
+ def _(self, target: str, value: str) -> str:
67
+ # Describe exactly what execute will do, without doing it (§4.3).
68
+ return f"Will set '{target}' to '{value}'."
69
+
70
+
71
+ if __name__ == "__main__":
72
+ from deepquery_sdk.mcp_emit import run_stdio
73
+
74
+ run_stdio(__CLASS_NAME__())
@@ -0,0 +1,23 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "__CONNECTOR_NAME__-connector"
7
+ version = "0.1.0"
8
+ description = "A Deep Query connector for __CONNECTOR_TITLE__."
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ dependencies = [
12
+ # Targets DeepQuerySDK major 1. A major bump means a fresh review (§11).
13
+ "deepquery-sdk>=1,<2",
14
+ ]
15
+
16
+ [project.optional-dependencies]
17
+ dev = ["pytest>=8", "pytest-asyncio>=0.25"]
18
+
19
+ [tool.hatch.build.targets.wheel]
20
+ only-include = ["connector.py"]
21
+
22
+ [tool.pytest.ini_options]
23
+ asyncio_mode = "auto"
@@ -0,0 +1,41 @@
1
+ """Local tests for the __CONNECTOR_TITLE__ connector.
2
+
3
+ These drive the connector through the mock agent over a real in-memory MCP
4
+ session — the same way Deep Query's Agent Layer will. Run with: pytest
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from deepquery_sdk import Credential, static_credential_provider
10
+ from deepquery_sdk.harness import MockAgent
11
+ from deepquery_sdk.validation import validate_connector
12
+
13
+ from connector import __CLASS_NAME__
14
+
15
+
16
+ def _connector() -> __CLASS_NAME__:
17
+ c = __CLASS_NAME__()
18
+ # Stand in for the gateway with a test credential so actions can execute.
19
+ c.set_credential_provider(static_credential_provider(Credential(token="test-token")))
20
+ return c
21
+
22
+
23
+ def test_connector_validates_clean():
24
+ report = validate_connector(_connector())
25
+ assert report.ok, report.format()
26
+
27
+
28
+ async def test_read_returns_provenance():
29
+ async with MockAgent(_connector()) as agent:
30
+ records = await agent.read("search", query="hello")
31
+ assert records, "expected at least one record"
32
+ assert records[0]["provenance"]["connector_name"] == "__CONNECTOR_NAME__"
33
+
34
+
35
+ async def test_action_preview_approve_and_reject():
36
+ async with MockAgent(_connector()) as agent:
37
+ approved = await agent.run_action("do_thing", approve=True, target="x", value="y")
38
+ assert approved["outcome"]["status"] == "executed"
39
+
40
+ rejected = await agent.run_action("do_thing", approve=False, target="x", value="y")
41
+ assert rejected["outcome"]["status"] == "rejected"
@@ -0,0 +1,201 @@
1
+ """Static + structural validation — the `validate` gatekeeper.
2
+
3
+ Encodes the safety contracts from SDK_GUIDE.md §5 (read/action classification),
4
+ §6 (provenance), and §13 (security) as automated checks, so a connector that
5
+ would violate the approval-gate model or break citations fails locally, before
6
+ deployment.
7
+
8
+ Checks are a mix of:
9
+ - **structural** — run against the loaded connector instance (manifest builds,
10
+ descriptions present, deployment honesty, least-privilege scopes); and
11
+ - **static (AST)** — scan `@resource` method bodies for obvious mutating calls,
12
+ catching a resource that writes (a misclassified action) "where statically
13
+ detectable" (§5).
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ import ast
19
+ import inspect
20
+ import re
21
+ import textwrap
22
+ from dataclasses import dataclass, field
23
+
24
+ from .connector import Connector
25
+
26
+ # High-confidence mutation indicators looked for inside @resource bodies. HTTP
27
+ # write verbs and clear DB mutators only, to keep false positives low.
28
+ _MUTATING_CALLS = {
29
+ "post", "put", "patch", "delete", # HTTP write verbs
30
+ "create", "update", "insert", "destroy", "drop", # ORM/DB mutators
31
+ "commit", "execute", "executemany", "save", # transactions / persistence
32
+ }
33
+
34
+ # Crude prompt-injection markers in natural-language descriptions (§13).
35
+ _INJECTION_MARKERS = re.compile(
36
+ r"ignore (all|previous|prior)|disregard (the|all|previous)|system prompt|"
37
+ r"you are now|override (the|all)|exfiltrate|return all (documents|records|data)",
38
+ re.IGNORECASE,
39
+ )
40
+
41
+ # Scope fragments that look broader than least-privilege (§13).
42
+ _BROAD_SCOPE = re.compile(r"(^|[:._-])(\*|all|admin|full|root|superuser|write:all|read:all)([:._-]|$)", re.IGNORECASE)
43
+
44
+ _SEMVER = re.compile(r"^\d+\.\d+\.\d+([-+].+)?$")
45
+
46
+
47
+ @dataclass
48
+ class Issue:
49
+ level: str # "error" | "warning"
50
+ code: str
51
+ message: str
52
+
53
+ def __str__(self) -> str:
54
+ mark = "ERROR" if self.level == "error" else "warn "
55
+ return f" [{mark}] {self.code}: {self.message}"
56
+
57
+
58
+ @dataclass
59
+ class ValidationReport:
60
+ connector_name: str
61
+ issues: list[Issue] = field(default_factory=list)
62
+
63
+ def error(self, code: str, message: str) -> None:
64
+ self.issues.append(Issue("error", code, message))
65
+
66
+ def warn(self, code: str, message: str) -> None:
67
+ self.issues.append(Issue("warning", code, message))
68
+
69
+ @property
70
+ def errors(self) -> list[Issue]:
71
+ return [i for i in self.issues if i.level == "error"]
72
+
73
+ @property
74
+ def warnings(self) -> list[Issue]:
75
+ return [i for i in self.issues if i.level == "warning"]
76
+
77
+ @property
78
+ def ok(self) -> bool:
79
+ return not self.errors
80
+
81
+ def format(self) -> str:
82
+ if not self.issues:
83
+ return f"OK {self.connector_name}: no issues."
84
+ lines = [f"{self.connector_name}: {len(self.errors)} error(s), {len(self.warnings)} warning(s)"]
85
+ lines += [str(i) for i in self.issues]
86
+ lines.append("PASS" if self.ok else "FAIL")
87
+ return "\n".join(lines)
88
+
89
+
90
+ class _MutationVisitor(ast.NodeVisitor):
91
+ """Collects (name, lineno) for calls that look like state mutations."""
92
+
93
+ def __init__(self) -> None:
94
+ self.found: list[tuple[str, int]] = []
95
+
96
+ def visit_Call(self, node: ast.Call) -> None: # noqa: N802 (ast API)
97
+ func = node.func
98
+ name = None
99
+ if isinstance(func, ast.Attribute):
100
+ name = func.attr
101
+ elif isinstance(func, ast.Name):
102
+ name = func.id
103
+ if name in _MUTATING_CALLS:
104
+ self.found.append((name, getattr(node, "lineno", 0)))
105
+ self.generic_visit(node)
106
+
107
+
108
+ def _check_descriptions(connector: Connector, report: ValidationReport) -> None:
109
+ for spec in list(connector.resources) + list(connector.actions):
110
+ if not (spec.description or "").strip():
111
+ report.error("DESC_MISSING", f"capability '{spec.name}' has an empty description (§4).")
112
+ elif _INJECTION_MARKERS.search(spec.description):
113
+ report.warn(
114
+ "DESC_INJECTION",
115
+ f"description for '{spec.name}' contains text resembling a prompt-injection "
116
+ f"instruction; descriptions are read by the planner (§13).",
117
+ )
118
+
119
+
120
+ def _check_actions(connector: Connector, report: ValidationReport) -> None:
121
+ for spec in connector.actions:
122
+ # Structural (also enforced at import time, re-checked for a clear message).
123
+ if not spec.has_preview():
124
+ report.error(
125
+ "ACTION_NO_PREVIEW",
126
+ f"action '{spec.name}' has no preview; every action must declare one (§4.3).",
127
+ )
128
+ if spec.execute_fn is None:
129
+ report.error("ACTION_NO_EXECUTE", f"action '{spec.name}' has no execute function.")
130
+
131
+
132
+ def _check_resources_are_readonly(connector: Connector, report: ValidationReport) -> None:
133
+ cls = type(connector)
134
+ for spec in connector.resources:
135
+ fn = getattr(cls, spec.attr_name, None)
136
+ if fn is None:
137
+ continue
138
+ try:
139
+ src = textwrap.dedent(inspect.getsource(fn))
140
+ tree = ast.parse(src)
141
+ except (OSError, TypeError, SyntaxError):
142
+ report.warn(
143
+ "RESOURCE_SOURCE_UNAVAILABLE",
144
+ f"could not read source of resource '{spec.name}' for static mutation analysis.",
145
+ )
146
+ continue
147
+ visitor = _MutationVisitor()
148
+ visitor.visit(tree)
149
+ for name, lineno in visitor.found:
150
+ report.error(
151
+ "RESOURCE_MUTATES",
152
+ f"resource '{spec.name}' appears to mutate external state via a "
153
+ f"'.{name}(...)' call (line {lineno}); resources must be read-only — "
154
+ f"declare this as an @action instead (§5).",
155
+ )
156
+
157
+
158
+ def _check_manifest_and_meta(connector: Connector, report: ValidationReport) -> None:
159
+ if not (connector.name or "").strip():
160
+ report.error("NAME_MISSING", "connector has no name.")
161
+ if not _SEMVER.match(connector.version or ""):
162
+ report.warn("VERSION_SEMVER", f"version '{connector.version}' is not semver x.y.z (§11).")
163
+ try:
164
+ manifest = connector.build_manifest()
165
+ except Exception as exc: # pragma: no cover - defensive
166
+ report.error("MANIFEST_BUILD", f"build_manifest() failed: {exc!r}")
167
+ manifest = None
168
+
169
+ # SDK compatibility (§11): the connector must target this SDK's major version.
170
+ if manifest is not None:
171
+ from .compat import check_manifest_compatibility
172
+
173
+ compat = check_manifest_compatibility(manifest)
174
+ if not compat.compatible:
175
+ report.error("SDK_INCOMPATIBLE", compat.reason)
176
+
177
+ # Deployment honesty (§13).
178
+ if connector.air_gapped_capable and connector.requires_network:
179
+ report.error(
180
+ "DEPLOY_CONTRADICTION",
181
+ "connector declares air_gapped_capable=True but requires_network=True; "
182
+ "an air-gapped connector cannot require external network access (§13).",
183
+ )
184
+
185
+ # Least-privilege scopes (§13).
186
+ for scope in connector.effective_auth_scopes:
187
+ if _BROAD_SCOPE.search(scope):
188
+ report.warn(
189
+ "SCOPE_BROAD",
190
+ f"OAuth scope '{scope}' looks broader than least-privilege (§13).",
191
+ )
192
+
193
+
194
+ def validate_connector(connector: Connector) -> ValidationReport:
195
+ """Run all checks against a loaded connector and return a report."""
196
+ report = ValidationReport(connector_name=connector.name or "<unnamed>")
197
+ _check_manifest_and_meta(connector, report)
198
+ _check_descriptions(connector, report)
199
+ _check_actions(connector, report)
200
+ _check_resources_are_readonly(connector, report)
201
+ return report
@@ -0,0 +1,195 @@
1
+ Metadata-Version: 2.4
2
+ Name: deepquery-sdk
3
+ Version: 1.0.0
4
+ Summary: Connector Development Kit for Deep Query — build MCP-emitting connectors with built-in read/action safety classification and provenance.
5
+ Project-URL: Homepage, https://github.com/GilbertAshivaka/deepquery-sdk
6
+ Project-URL: Repository, https://github.com/GilbertAshivaka/deepquery-sdk
7
+ Project-URL: Changelog, https://github.com/GilbertAshivaka/deepquery-sdk/blob/main/CHANGELOG.md
8
+ Project-URL: Documentation, https://github.com/GilbertAshivaka/deepquery-sdk/blob/main/README.md
9
+ Author-email: Gilbert Ashivaka <gilbertashivaka@gmail.com>
10
+ License: Apache-2.0
11
+ License-File: LICENSE
12
+ Keywords: connector,deepquery,mcp,model-context-protocol,rag
13
+ Classifier: Development Status :: 5 - Production/Stable
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: Apache Software License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
22
+ Requires-Python: >=3.10
23
+ Requires-Dist: mcp<2,>=1.10
24
+ Requires-Dist: pydantic<3,>=2
25
+ Provides-Extra: dev
26
+ Requires-Dist: build>=1.2; extra == 'dev'
27
+ Requires-Dist: pytest-asyncio>=0.25; extra == 'dev'
28
+ Requires-Dist: pytest>=8; extra == 'dev'
29
+ Description-Content-Type: text/markdown
30
+
31
+ # DeepQuerySDK — Connector Development Kit
32
+
33
+ Build connectors for Deep Query. A connector you write with this SDK **emits a
34
+ standard [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server**
35
+ — so Deep Query consumes it through the exact same interface as any public MCP
36
+ server. You never touch JSON-RPC, transport, or schema plumbing.
37
+
38
+ > **Status: v1.0.0 — all four build phases complete.** Core contracts (Phase 1),
39
+ > the gated **preview → approve → execute / reject** lifecycle + OAuth 2.1 PKCE
40
+ > scaffolding + credential injection (Phase 2), the `deepquery` **CLI** and
41
+ > **mock-agent harness** with the §5/§6/§13 contracts encoded as `validate`
42
+ > checks (Phase 3), and the semver **compatibility contract** + packaging
43
+ > (Phase 4). The SDK contract is at **major version 1**: connectors declaring
44
+ > `sdk_major_version = 1` are loadable by this runtime.
45
+
46
+ ## What you define
47
+
48
+ A connector is a subclass of `Connector` that declares three things:
49
+
50
+ | You define | What it is | Gated? |
51
+ |---|---|---|
52
+ | **Resources** | read-only data the agent can retrieve and **cite** | no |
53
+ | **Actions** | operations that change external state | yes (preview → execute) |
54
+ | **Auth** | how the connector authenticates to the external system | n/a |
55
+
56
+ Every read carries a **provenance envelope** so live data can be cited honestly.
57
+ Every action is tagged `dq.mutates: true` in the emitted MCP server so Deep
58
+ Query's approval gate knows it must be confirmed by a human.
59
+
60
+ ## Install (development)
61
+
62
+ ```powershell
63
+ # from the DeepQuerySDK/ folder, using the bundled venv
64
+ venv\Scripts\python.exe -m pip install -e .
65
+ ```
66
+
67
+ ## 60-second example
68
+
69
+ ```python
70
+ from deepquery_sdk import Connector, OAuth2Auth, resource, action
71
+
72
+ class JiraConnector(Connector):
73
+ name = "jira"
74
+ version = "0.1.0"
75
+ description = "Read and act on Jira issues."
76
+
77
+ # Declare OAuth 2.1 with least-privilege scopes. The gateway runs/stores the
78
+ # grant and injects the token; this connector never stores credentials.
79
+ auth = OAuth2Auth(
80
+ authorize_endpoint="https://auth.atlassian.com/authorize",
81
+ token_endpoint="https://auth.atlassian.com/oauth/token",
82
+ scopes=["read:jira-work", "write:jira-work"],
83
+ )
84
+ requires_network = True
85
+
86
+ @resource(description="Search Jira issues by text query.",
87
+ input_schema={"type": "object",
88
+ "properties": {"query": {"type": "string"}},
89
+ "required": ["query"]})
90
+ def search_issues(self, query: str):
91
+ # ... call the real Jira API here ...
92
+ return [
93
+ self.cite(
94
+ {"key": "DQ-431", "summary": "Login flow broken", "status": "In Review"},
95
+ source_object_id="DQ-431",
96
+ title_or_label="DQ-431 — Login flow broken",
97
+ deep_link="https://example.atlassian.net/browse/DQ-431",
98
+ mutability_note="live status field",
99
+ )
100
+ ]
101
+
102
+ @action(description="Create a new Jira issue.",
103
+ input_schema={"type": "object",
104
+ "properties": {"project": {"type": "string"},
105
+ "summary": {"type": "string"}},
106
+ "required": ["project", "summary"]})
107
+ def create_issue(self, project: str, summary: str):
108
+ # only ever called after the approval gate confirms the preview.
109
+ auth = self.apply_auth() # headers built from the injected credential
110
+ return {"created": f"{project}-NEW", "summary": summary}
111
+
112
+ @create_issue.preview
113
+ def _(self, project: str, summary: str) -> str:
114
+ return f"Will create a new issue in project '{project}' titled '{summary}'."
115
+ ```
116
+
117
+ Emit and serve it as an MCP server (the gateway injects the credential):
118
+
119
+ ```python
120
+ from deepquery_sdk import Credential, static_credential_provider
121
+ from deepquery_sdk.mcp_emit import run_stdio
122
+
123
+ connector = JiraConnector()
124
+ connector.set_credential_provider(static_credential_provider(Credential(token="...")))
125
+ run_stdio(connector)
126
+ ```
127
+
128
+ ## The gated action lifecycle
129
+
130
+ Calling an action does **not** execute it. It returns a preview and a single-use
131
+ approval token; the gateway drives the decision through two control tools:
132
+
133
+ ```
134
+ call create_issue(args) -> { status: "preview", approval_token, preview, arguments }
135
+ call dq.execute_action(token) -> runs execute() for exactly those args (after human approval)
136
+ call dq.reject_action(token) -> discards the action; it never runs
137
+ ```
138
+
139
+ The token binds the previewed arguments, so execute can never drift from what the
140
+ human approved, and a rejected/used token can never run.
141
+
142
+ ## The `deepquery` CLI
143
+
144
+ ```bash
145
+ deepquery scaffold acme-crm # generate a new connector from the template
146
+ deepquery validate connector.py # enforce the §5/§6/§13 safety contracts
147
+ deepquery manifest connector.py # print/export the connector manifest
148
+ deepquery run-dev connector.py # drive it interactively with the mock agent
149
+ deepquery emit connector.py --out dist/ # produce the deployable MCP server artifact
150
+ ```
151
+
152
+ A target can be a `path/to/connector.py`, a directory containing `connector.py`,
153
+ or a `module.path:ClassName`. `validate` is the gatekeeper: it statically scans
154
+ `@resource` bodies for mutating calls and **fails a resource that writes** (a
155
+ misclassified action), plus checks descriptions, manifest, deployment honesty,
156
+ and least-privilege scopes.
157
+
158
+ The dev harness (`deepquery_sdk.harness.MockAgent`) discovers a connector over a
159
+ real in-memory MCP session and drives reads (inspecting provenance) and the full
160
+ preview → approve / reject action flow — the same sequence the real Agent Layer
161
+ uses.
162
+
163
+ ## Try it without the test suite
164
+
165
+ ```powershell
166
+ # read path + classification + provenance, over a real stdio MCP server
167
+ venv\Scripts\python.exe examples\manual_client.py
168
+
169
+ # the full preview -> approve -> execute and preview -> reject flow
170
+ venv\Scripts\python.exe examples\manual_action_flow.py
171
+ ```
172
+
173
+ See [`examples/jira_connector/`](examples/jira_connector/) for the full runnable
174
+ connector used in the Phase 1 and Phase 2 tests.
175
+
176
+ ## Versioning & compatibility
177
+
178
+ The SDK follows [SemVer](https://semver.org); see [CHANGELOG.md](CHANGELOG.md).
179
+ Every connector manifest declares the SDK **major** version it targets, and the
180
+ gateway calls `assert_compatible(manifest)` before loading — refusing a connector
181
+ built against an incompatible major with a clear error. Breaking changes ship
182
+ with a guide in [MIGRATIONS.md](MIGRATIONS.md).
183
+
184
+ ## Release / publishing (maintainers)
185
+
186
+ Distributions are built with `python -m build` into `dist/`. To publish to PyPI:
187
+
188
+ ```bash
189
+ python -m build # build sdist + wheel into dist/
190
+ python -m twine check dist/* # validate metadata
191
+ python -m twine upload dist/* # publish (requires PyPI credentials)
192
+ ```
193
+
194
+ Tag the release `v<version>` and ensure `version` in `pyproject.toml` matches
195
+ `SDK_VERSION` (a test enforces this against the installed package).
@@ -0,0 +1,32 @@
1
+ deepquery_sdk/__init__.py,sha256=ljlvmc-k3UNY5wYmCVa_s0aZbG49aXaTWnXjP2aCuCM,2323
2
+ deepquery_sdk/action.py,sha256=5x1h1xyefYOMbkhtyPN9Vf9mjkI7HSLSh-Ky9yFPAr4,3516
3
+ deepquery_sdk/classification.py,sha256=8u3rvGlmK5Qku6l5p1fqxMjKNqqdbnuawDzS98SrkDw,1536
4
+ deepquery_sdk/compat.py,sha256=0r_dOdT8PZYMsVXkn13wiXAdLeFYrfAk2pGGbo8jIOU,2924
5
+ deepquery_sdk/connector.py,sha256=XAyovORa8VATBh5L5T-VU4dQM3Kew0Oa1WsNXjBDKEs,11824
6
+ deepquery_sdk/gate.py,sha256=3SeGuNJLKn3VJL7lflDgnWZuC8M-MW1L4y7FT_5s9lI,3171
7
+ deepquery_sdk/manifest.py,sha256=sb2TO5s5QAnyqIrgUtWFXSUP4SrAiKmaWnnJbWUlLa8,2654
8
+ deepquery_sdk/provenance.py,sha256=TmYNrjOfxAOZI3oncGHIwZo9Af2nI2cLiaAclZvkoDY,2497
9
+ deepquery_sdk/resource.py,sha256=bsflvP09c__BQLdnCYORD6PMTOXAULDVI2t2m3QBv4k,2051
10
+ deepquery_sdk/validation.py,sha256=9EvMwkeHLY0diF7thGK9XmAelf_F04zbCBZ245I9tDw,7682
11
+ deepquery_sdk/auth/__init__.py,sha256=SEDgUezt3x3UiT2avO0HsF_hoiTEPDaWI1TOiolza0Y,1017
12
+ deepquery_sdk/auth/base.py,sha256=JxErZ2U6PQOU6DJTqNhReZMMlhvpxSRm1wtTFUtyQKA,3287
13
+ deepquery_sdk/auth/oauth2.py,sha256=fAbZv5Ny-9vDHv0P3_Ait94WVZ4DSCatolISjRcjbOw,3004
14
+ deepquery_sdk/auth/strategies.py,sha256=SgyMErzqqgLRVtZ5udt7DwJpiEJG-ECCyBF89v7qPTY,3285
15
+ deepquery_sdk/cli/__init__.py,sha256=iAmOGZvrhYJ20s1BkFmBB47A0sQx1fedA07sC1bibHQ,139
16
+ deepquery_sdk/cli/__main__.py,sha256=0LgqR-qjp_UZVMpjbMXkk4HhioAIpARaYkfMrwzhIQo,2513
17
+ deepquery_sdk/cli/commands.py,sha256=8-4oApFvnblBOxd2Cd8lj8OtiPA5xcS9KGjIrCIIHMo,7563
18
+ deepquery_sdk/cli/loader.py,sha256=WevWoXpHQjp5v92aF6N-IhtyuvIQ2bXSRRpfGjDr4Yk,3326
19
+ deepquery_sdk/harness/__init__.py,sha256=6n4u0RRqgpVgefEqn7XvuNKwf1F-9HCwQ1KwTCWCZR8,164
20
+ deepquery_sdk/harness/mock_agent.py,sha256=1teXGsc7TnakTNSrusfGfuxaZtWefSPCIHZPDCGI7Zw,5478
21
+ deepquery_sdk/mcp_emit/__init__.py,sha256=qMZWxucslEXOxQhfnf65LifjighelKb1MDndA7GF_Rs,205
22
+ deepquery_sdk/mcp_emit/emitter.py,sha256=8_vW-5atljba7X5u0lngILkoec42-GTs7ygKcEkQ89I,6806
23
+ deepquery_sdk/templates/connector/.gitignore.tmpl,sha256=XiYls0YMt-7cQ6bDLIs2bjzgovbsp2DA8PN6OL_0Mbc,81
24
+ deepquery_sdk/templates/connector/README.md.tmpl,sha256=NrTNm-8ww4YAeMBb-VkbyTG33JwMYgE6QI4qufURyqI,883
25
+ deepquery_sdk/templates/connector/connector.py.tmpl,sha256=MwQKzlBg-fiAwrb1MtaxG0eeqj6Zu-cPAQpHL3sXnHc,2907
26
+ deepquery_sdk/templates/connector/pyproject.toml.tmpl,sha256=k4wGRd_UNMmercQ6U5RSaQpUgu43wNpKX9YSMM82l9g,569
27
+ deepquery_sdk/templates/connector/tests/test_connector.py.tmpl,sha256=Vvh0hb0xn6k6UR7woHStJLN78Hty5c2oScmUUMNTDtU,1510
28
+ deepquery_sdk-1.0.0.dist-info/METADATA,sha256=gqYaknbqGcqA_uF_I1QOia-NN9UNyn_wclAymlscMi4,8478
29
+ deepquery_sdk-1.0.0.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
30
+ deepquery_sdk-1.0.0.dist-info/entry_points.txt,sha256=8PgvowkTPbukZyAxzSKuRrBRVG4uO3_ubHQvgJD3Z1Q,62
31
+ deepquery_sdk-1.0.0.dist-info/licenses/LICENSE,sha256=f1SM0QFeSzU-QMK2DLqc0ZXyonbBk_Mp01DU3QDvZlM,10575
32
+ deepquery_sdk-1.0.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.30.1
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ deepquery = deepquery_sdk.cli.__main__:main