dataapp-resource-proxy 0.1.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.
@@ -0,0 +1,6 @@
1
+ Metadata-Version: 2.5
2
+ Name: dataapp-resource-proxy
3
+ Version: 0.1.0
4
+ Summary: Run-scoped client for managed browser, proxy and CAPTCHA resources
5
+ Requires-Python: >=3.11
6
+ Requires-Dist: httpx<1,>=0.28
@@ -0,0 +1,273 @@
1
+ # DataApp Resource Proxy client
2
+
3
+ This package acquires run-scoped DataOS browser and proxy resources. It does not
4
+ contain supplier credentials, crawler code, or server components.
5
+
6
+ The local candidate supports `captcha_types(type=..., refresh=True)` and generic
7
+ `solve_captcha(type=..., task_variant=..., parameters=...)`. Query the directory
8
+ before selecting new variants. The developer directory only returns variants
9
+ whose Billing classifications have effective supplier-cost quotes. Its
10
+ `pricing_version` identifies the price snapshot used for that decision, and
11
+ `available_billing_types` lists the enabled classifications without exposing
12
+ supplier prices. Queries do not submit solver tasks; explicit solves are
13
+ metered. Structured answers are available through `CaptchaTask.data`.
14
+ See [the RP task-directory contract](../../docs/resources/captcha-directory.md).
15
+ These fields require matching service/Runtime bridge versions; updating this
16
+ client alone does not upgrade a deployed platform.
17
+
18
+ CAPTCHA directory results use the same short client cache as other resource
19
+ catalogs. Pass `refresh=True` when the UI needs current availability. The
20
+ directory is advisory: Resource Proxy performs the authoritative check again at
21
+ submission, so manually supplied or stale parameters cannot enable an unpriced
22
+ task. Older directory responses without availability metadata are rejected
23
+ instead of being treated as unrestricted support.
24
+
25
+ The current development line supports account-environment routing, regional
26
+ resource receipts, and the `DEFERRED` resource-cost receipt contract.
27
+
28
+ For local development against pre, only the developer's ordinary API Key is
29
+ required. The client defaults to the `bazhuayu_pre` account, uses the verified
30
+ domestic and overseas pre entries, and selects the resource node independently
31
+ from the account and Billing environment.
32
+
33
+ Managed proxies and CAPTCHA solves accrue resource costs. After the developer
34
+ confirms that the local test may use these services, run the masked setup:
35
+
36
+ ```sh
37
+ python -m dataapp_resource_proxy configure
38
+ ```
39
+
40
+ The command reads the Key without displaying it and stores it outside the
41
+ project in a mode-`600` per-user file. Obtain the Key from **Account Center >
42
+ API Keys**: [pre](https://pre.bazhuayu.com/console/account-center/api-keys) for
43
+ the default pre setup, or
44
+ [production](https://www.bazhuayu.com/console/account-center/api-keys) for a
45
+ production account. Never paste a Key into chat or package it with an App.
46
+ Platform Runs use injected run identity and do not need a developer API Key.
47
+ When local code runs inside a container, the host's per-user file is not visible
48
+ automatically. Mount that one file read-only at the same path, or pass
49
+ `DATAAPP_API_KEY` through the container's secret/environment mechanism. Do not
50
+ copy the file into the image or build context.
51
+
52
+ Configure the application process with the following variables:
53
+
54
+ ```sh
55
+ DATAAPP_API_KEY=<developer-api-key>
56
+ DATAOS_RESOURCE_READ_TIMEOUT_SECONDS=10
57
+ ```
58
+
59
+ `DATAAPP_API_KEY` is the canonical process override. The deprecated
60
+ `DATAOS_API_KEY` remains a compatibility fallback; conflicting values are
61
+ rejected. The per-user setup file is loaded only for missing values, so an
62
+ explicit process value takes precedence. `DATAOS_APP_ID` remains optional
63
+ metadata and is not a prerequisite for local managed resources.
64
+
65
+ Regional `usages()` and `resource_charges()` reads use a 10-second per-node
66
+ deadline by default, so one slow node does not hide another node's result. Set
67
+ `DATAOS_RESOURCE_READ_TIMEOUT_SECONDS` to a finite value greater than 0 and at
68
+ most 30 seconds when a different local deadline is required. The
69
+ `regional_read_timeout` argument to `ResourceProxy.from_env()` takes precedence
70
+ over the environment value. Hosts can read the validated
71
+ `resources.regional_read_timeout` property when applying their own bounded
72
+ execution-shutdown guard.
73
+
74
+ The access profiles `bazhuayu_overseas_pre` and `bazhuayu_overseas` select an
75
+ overseas node while retaining the corresponding `bazhuayu_pre` or `bazhuayu`
76
+ account and Billing identity. They are routing profiles, not separate accounts.
77
+ `octoparse_pre` and `octoparse` remain distinct account environments for
78
+ compatibility. A node being reachable or healthy does not prove that identity
79
+ validation, supplier allocation, target-site access, or business-data
80
+ extraction will succeed.
81
+
82
+ The built-in pre endpoints are `https://pre-resource-proxy.bazhuayu.com:443`
83
+ for domestic resources and
84
+ `https://pre-resource-proxy-overseas.bazhuayu.com:443` for overseas resources.
85
+ Certificate and hostname verification stay enabled. Explicit URL variables below
86
+ can override these defaults for an isolated test or rollback.
87
+
88
+ Production profiles (`bazhuayu`, `bazhuayu_overseas`, and `octoparse`) have no built-in node
89
+ addresses until their public endpoints are verified. Configure one explicit
90
+ single-node URL:
91
+
92
+ ```sh
93
+ DATAOS_RESOURCE_PROXY_URL=https://resource-proxy.example.com
94
+ ```
95
+
96
+ Or configure regional nodes independently:
97
+
98
+ ```sh
99
+ DATAOS_RESOURCE_PROXY_DOMESTIC_URL=https://domestic-resource-proxy.example.com
100
+ DATAOS_RESOURCE_PROXY_OVERSEAS_URL=https://overseas-resource-proxy.example.com
101
+ ```
102
+
103
+ Explicit URL variables override automatic pre-node selection. Supplying any
104
+ regional URL enables explicit regional mode, so an omitted region remains
105
+ unconfigured. This permits an overseas-only setup without routing domestic work
106
+ to the overseas node. `DATAOS_RESOURCE_PROXY_URL` keeps legacy single-node
107
+ semantics and is never supplemented with an automatic overseas node.
108
+
109
+ Then use the same resource API:
110
+
111
+ ```python
112
+ from dataapp_resource_proxy import ResourceProxy
113
+
114
+ async with ResourceProxy.from_env() as resources:
115
+ proxy = await resources.proxy(
116
+ country="US",
117
+ proxy_group="overseas_basic",
118
+ )
119
+ print(proxy.lease_id)
120
+ ```
121
+
122
+ The API Key, returned proxy URL, and browser connection headers are secrets. Keep
123
+ them in local environment configuration; do not log, package, or store them in
124
+ application data. See `local-resource.env.example` for a value-free setup file.
125
+
126
+ New managed proxy requests accept `auto`, `domestic_basic`, `overseas_basic`,
127
+ or `overseas_enhanced`. `auto` uses the basic managed service. Supplier ordering
128
+ and location or duration support come from Resource Proxy's published catalog;
129
+ the client does not select suppliers. Existing handles may still report a legacy
130
+ group value from historical leases and remain readable.
131
+
132
+ Query the managed catalog before asking a user to choose a location. This is also
133
+ the preferred flow for an AI-generated DataApp:
134
+
135
+ Catalog methods require a node with the catalog API enabled. Older nodes can
136
+ still issue leases but return HTTP 404 for catalog queries. Report that capability
137
+ as unavailable; do not treat it as an empty geographic coverage list or silently
138
+ allocate a paid lease to discover coverage. A client package upgrade does not
139
+ upgrade the Resource Proxy server.
140
+
141
+ ```python
142
+ async with ResourceProxy.from_env() as resources:
143
+ groups = await resources.proxy_groups(network_preference="overseas")
144
+ countries = await resources.proxy_locations(
145
+ proxy_group="overseas_basic",
146
+ network_preference="overseas",
147
+ )
148
+ states = await resources.proxy_locations(
149
+ proxy_group="overseas_basic",
150
+ country="US",
151
+ )
152
+ if not states["items"]:
153
+ raise RuntimeError("No state coverage is currently listed; check the catalog status")
154
+ proxy = await resources.proxy(
155
+ proxy_group="overseas_basic",
156
+ country="US",
157
+ state=states["items"][0]["code"],
158
+ )
159
+ ```
160
+
161
+ Catalog results describe configured geographic coverage. They are not a promise
162
+ of real-time supplier inventory, so a later lease request can still report that
163
+ a route is temporarily unavailable. `ResourceProxy.proxy_location_hints()`
164
+ returns a small non-authoritative list of popular countries for empty-state UI;
165
+ it never replaces a failed catalog query. Catalog queries use a 30-second,
166
+ per-client cache; pass `refresh=True` to bypass it.
167
+
168
+ For a locally developed Code App, `DATAOS_APP_ID` and `DATAOS_APP_VERSION` are
169
+ optional attribution metadata. The resource flow uses the ordinary platform
170
+ `DATAAPP_API_KEY`; it does not create a separate billing Key.
171
+
172
+ Inside a platform DataApp, obtain the same client from the Runtime so the
173
+ DataHub backend can bind requests to the current Run and Attempt without
174
+ forwarding the developer API key:
175
+
176
+ ```python
177
+ from bazhuayu_dataapp import DataApp
178
+
179
+ async with DataApp:
180
+ resources = DataApp.resources()
181
+ browser = await resources.browser(session_timeout=900)
182
+ ws_url, headers = await browser.connection()
183
+ ```
184
+
185
+ Resource handles are owned by the client. Close a handle when it is no longer
186
+ needed, or close the client to release all remaining handles and its execution.
187
+ `ProxyResource.rotate_credentials()` rotates only the temporary DataOS gateway
188
+ username/password. It does not claim to replace the supplier session or exit IP.
189
+ Creation requests accept an `idempotency_key`; reuse the same value only when
190
+ retrying the same logical creation after an uncertain transport outcome. A
191
+ browser call also gets an allocation `slot_id`, so independent calls do not
192
+ share a CDP session. By default the slot is derived from the idempotency key;
193
+ reusing that key safely replays the same logical creation. If a slot is supplied
194
+ explicitly, reuse it together with the key. One client rejects a second live
195
+ handle for the same remote browser so closing one crawler cannot stop another's
196
+ shared session. Proxy leases use the same single-live-handle rule.
197
+
198
+
199
+ ## Managed CAPTCHA resources
200
+
201
+ The default SDK path is the platform-managed cloud API below. Supplier
202
+ credentials stay in Resource Proxy. A native browser extension is an explicit
203
+ advanced option for developers who supply and manage their own vendor account;
204
+ it is not enabled by local API-Key setup.
205
+
206
+ Managed CAPTCHA calls use the overseas Resource Proxy node by default while
207
+ retaining the caller's Bazhuayu account and Billing environment. Creation and
208
+ polling stay on that node. Pass the same explicit `network_preference` to both
209
+ operations only when testing another configured node.
210
+
211
+ The same execution can call `create_captcha_task`, `get_captcha_task`, or
212
+ `solve_captcha`. For image recognition use `type="image_to_text"`, a one-line
213
+ Base64 `image_body`, and optional `capmonster_module="botdetect"` (or another
214
+ configured module). Module selection is a recognizer parameter, not webpage
215
+ CAPTCHA detection. Reuse the same `idempotency_key` when retrying a submission;
216
+ never automatically resubmit an unknown outcome with a new key.
217
+
218
+ `CaptchaTask` returns `node_id/network`; use the creating node for all polls.
219
+ Solutions are excluded from repr. A solver answer still requires validation by
220
+ the target site and does not prove business acquisition success.
221
+
222
+ `captcha_plugin_grant(allowed_types=["image_to_text"], ttl_seconds=300)` returns
223
+ an adapter URL and a secret short-lived key for the explicitly managed extension.
224
+ Other canonical types are `turnstile`, `recaptcha_v2`, and
225
+ `recaptcha_v2_enterprise`; `allowed_hosts` can narrow widget task sites. This key
226
+ cannot authenticate IP, Browser, model, or execution APIs. Its
227
+ `protocol_version` is currently integer `1`. The extension must use the adapter
228
+ for create/poll/credit checks, preserve `dataosRequestId` across retries, and
229
+ return opaque `taskId` unchanged; changing an original extension's base URL alone
230
+ is insufficient. There is no upstream vendor credential in the grant.
231
+
232
+ ## Local debug billing
233
+
234
+ For opted-in local executions, the SDK logs one warning before the first
235
+ managed IP lease request, CAPTCHA submission, plugin grant, or model request.
236
+ IP traffic, CAPTCHA solves, and model requests can charge the developer
237
+ account. Pod cost appears separately in cloud debug.
238
+
239
+ ```python
240
+ async with ResourceProxy.from_env() as resources:
241
+ completion = await resources.chat_completion({
242
+ "model": "your-model-alias",
243
+ "messages": [{"role": "user", "content": "Hello"}],
244
+ })
245
+
246
+ receipt = await resources.resource_charge()
247
+ if receipt is not None:
248
+ print(receipt["state"], receipt["currency"], receipt["expected_amount"], receipt["actual_amount"])
249
+ ```
250
+
251
+ Read `resource_charge()` during the execution or after it closes. Expected
252
+ and actual amounts retain the service's decimal strings. Resource costs will be
253
+ deducted from developer earnings at settlement, and the remaining earnings will be
254
+ paid out after deduction. `DEFERRED` means the cost has been recorded for deduction;
255
+ it does not confirm a completed deduction. An `actual_amount` of `None` means there
256
+ is no confirmed wallet amount. `resource_charge()`
257
+ returns `None` when managed billing is disabled for the execution or the
258
+ server predates managed billing. A `None` receipt is an unavailable receipt
259
+ payload, not proof that the resource was free or that no charge was recorded.
260
+
261
+ ## Managed model requests
262
+
263
+ Use `chat_completion()` with the local client or with `DataApp.resources()`
264
+ in a cloud Run. The helper sends one non-streaming request. Omit `stream` or
265
+ set it to `False`. If your caller may retry after a transport error, pass a
266
+ stable `idempotency_key` and reuse it for the same logical request. The
267
+ helper generates a key when you omit it.
268
+
269
+ The direct HTTP/SSE endpoint `/v1/model-proxy/chat/completions` uses the
270
+ execution identity. Raw clients must send `Idempotency-Key` for managed
271
+ billing and reuse it on retries. Replaying a dispatched key returns a
272
+ conflict. See the [server contract](../../docs/resources/captcha-model.md)
273
+ for the inline-image format, model alias policy, and incomplete usage semantics.
@@ -0,0 +1,22 @@
1
+ # Prefer `python -m dataapp_resource_proxy configure`: it prompts without echo,
2
+ # stores this value outside the project, and applies private file permissions.
3
+ # This environment variable is the explicit process override. Never commit a
4
+ # real value, paste it into chat, or package it with a Data App.
5
+ DATAAPP_API_KEY=replace-with-developer-api-key
6
+
7
+ # Account Center > API Keys:
8
+ # pre: https://pre.bazhuayu.com/console/account-center/api-keys
9
+ # production: https://www.bazhuayu.com/console/account-center/api-keys
10
+
11
+ # Local debug defaults to bazhuayu_pre. These access profiles are optional;
12
+ # overseas profiles keep the same Bazhuayu account and Billing identity.
13
+ # DATAAPP_ENVIRONMENT=bazhuayu_overseas_pre
14
+
15
+ # Pre node addresses are built in. DATAOS_* URL variables remain expert
16
+ # transport overrides for isolated tests and verified production deployments.
17
+ # Uncomment explicit URLs only to override automatic pre-node selection or to
18
+ # configure a verified production deployment. Supplying one regional URL leaves
19
+ # the other region unconfigured.
20
+ # DATAOS_RESOURCE_PROXY_URL=https://single-node.example.com
21
+ # DATAOS_RESOURCE_PROXY_DOMESTIC_URL=https://domestic-node.example.com
22
+ # DATAOS_RESOURCE_PROXY_OVERSEAS_URL=https://overseas-node.example.com
@@ -0,0 +1,33 @@
1
+ [build-system]
2
+ requires = ["hatchling>=1.27"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "dataapp-resource-proxy"
7
+ version = "0.1.0"
8
+ description = "Run-scoped client for managed browser, proxy and CAPTCHA resources"
9
+ requires-python = ">=3.11"
10
+ dependencies = ["httpx>=0.28,<1"]
11
+
12
+ [dependency-groups]
13
+ dev = ["pytest>=8,<10", "pytest-asyncio>=0.24,<2", "ruff>=0.9", "mypy>=1.13"]
14
+
15
+ [tool.hatch.build.targets.wheel]
16
+ packages = ["src/dataapp_resource_proxy"]
17
+
18
+ [tool.pytest.ini_options]
19
+ asyncio_mode = "auto"
20
+ asyncio_default_fixture_loop_scope = "function"
21
+ testpaths = ["tests"]
22
+
23
+ [tool.ruff]
24
+ target-version = "py311"
25
+ line-length = 100
26
+
27
+ [tool.ruff.lint]
28
+ select = ["E", "F", "I", "UP", "B"]
29
+
30
+ [tool.mypy]
31
+ python_version = "3.11"
32
+ check_untyped_defs = true
33
+ ignore_missing_imports = true
@@ -0,0 +1,15 @@
1
+ """Client for DataOS managed runtime resources."""
2
+
3
+ from .client import ResourceProxy, ResourceTransport
4
+ from .errors import ResourceProxyError
5
+ from .handles import BrowserResource, CaptchaPluginGrant, CaptchaTask, ProxyResource
6
+
7
+ __all__ = [
8
+ "BrowserResource",
9
+ "CaptchaTask",
10
+ "CaptchaPluginGrant",
11
+ "ProxyResource",
12
+ "ResourceProxy",
13
+ "ResourceProxyError",
14
+ "ResourceTransport",
15
+ ]
@@ -0,0 +1,65 @@
1
+ """Command-line helpers for local DataApp resource configuration."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ import getpass
7
+ import os
8
+ import warnings
9
+ from collections.abc import Sequence
10
+
11
+ from ._local_config import (
12
+ load_project_config,
13
+ resolve_config_environment,
14
+ save_local_config,
15
+ )
16
+ from .errors import ResourceProxyError
17
+
18
+
19
+ def _configure() -> int:
20
+ try:
21
+ project = load_project_config(os.environ)
22
+ environment = resolve_config_environment(os.environ, project)
23
+ except ResourceProxyError as error:
24
+ print(f"配置错误:{error}")
25
+ return 2
26
+ if environment is None:
27
+ print(
28
+ "未找到当前项目的 .dataapp-sdk.json。请在下载的 SDK 项目根目录运行,"
29
+ "或为独立项目显式设置 DATAAPP_ENVIRONMENT。"
30
+ )
31
+ return 2
32
+ print("平台托管 IP 代理和验证码服务会按实际用量产生资源费用。")
33
+ if project is not None:
34
+ print(f"请从当前平台账户中心获取 API Key:{project.api_keys_url}")
35
+ answer = input("确认在本地调试中使用这些收费资源?[y/N] ").strip().lower()
36
+ if answer not in {"y", "yes"}:
37
+ print("未保存配置,也不会发起任何托管资源请求。")
38
+ return 1
39
+ try:
40
+ with warnings.catch_warnings():
41
+ warnings.simplefilter("error", getpass.GetPassWarning)
42
+ api_key = getpass.getpass("请粘贴账户中心的 API Key(输入不会显示):").strip()
43
+ except (EOFError, KeyboardInterrupt, getpass.GetPassWarning):
44
+ print("当前终端无法安全隐藏输入;未保存配置。请在交互式终端重新运行。")
45
+ return 2
46
+ if not api_key:
47
+ print("API Key 不能为空;未保存配置。")
48
+ return 2
49
+ path = save_local_config(api_key, environment=environment)
50
+ print(f"配置已安全保存到 {path},文件权限已设置为 600。")
51
+ return 0
52
+
53
+
54
+ def main(argv: Sequence[str] | None = None) -> int:
55
+ parser = argparse.ArgumentParser(prog="python -m dataapp_resource_proxy")
56
+ commands = parser.add_subparsers(dest="command", required=True)
57
+ commands.add_parser("configure", help="configure local managed resources securely")
58
+ options = parser.parse_args(argv)
59
+ if options.command == "configure":
60
+ return _configure()
61
+ return 2
62
+
63
+
64
+ if __name__ == "__main__":
65
+ raise SystemExit(main())