mostlyright-data 0.29.9__tar.gz → 0.29.10__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.
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/PKG-INFO +1 -1
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/pyproject.toml +1 -1
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/preparing-table-search.md +28 -2
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/router.py +4 -1
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/session.py +68 -5
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/v4_public.py +38 -19
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/.gitignore +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/README.md +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/scripts/hatch_build.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/SKILL.md +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/agents/openai.yaml +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/1-open-the-page-and-the-link-to-it-in-the-first-message.md +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/2-brief-two-to-four-questions-each-with-a-recommended-answer.md +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/3-probe-read-a-source-before-committing-to-it.md +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/4-decide-say-what-you-chose-what-you-refused-and-ask-one-question.md +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/5-draft-one-recipe-document-one-call.md +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/6-build-one-run-sized-to-acquire-every-measured-source-whole.md +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/7-interrogate-ask-the-run-what-it-actually-delivered.md +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/8-fix-revise-the-document-and-register-it-again.md +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/9-present-only-what-survived-inspection-with-caveats.md +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/agent-protocol.md +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/autonomous-delivery.md +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/before-the-first-tool-call.md +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/boundaries.md +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/cloud-authentication-preflight.md +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/commands.md +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/cross-repository-protocol-reference.md +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/installation-parity.md +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/live-run.md +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/making-a-table-incremental.md +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/narrating-the-run.md +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/not-hosted-yet.md +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/one-install.md +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/prediction-labels.md +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/promote.md +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/readers.md +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/receipts.md +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/recording-a-stream-venue.md +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/recovering-an-import-failure.md +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/reference-pages.md +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/required-protocol.md +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/source-credentials.md +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/sources.md +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/the-one-thing-to-say-about-the-skill-itself.md +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/transforms.md +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/user-communication-contract.md +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/writing-a-decision-record.md +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/scripts/write_research_notebook.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/__init__.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/agent_protocol.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/canonical.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/formats.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/hosted_crawler_protocol.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/key_seam.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/page_coverage.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/part_check_evidence.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/session_probes.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/skill_assets.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/table_manifest.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/__init__.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/acquire.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/acquire_cancel.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/activity.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/approvals.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/categories.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/commands.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/dataset-categories-v1.json +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/download.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/fast_features.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/narrative.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/parity.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/probe.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/progress_rate.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/progress_vocabulary.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/propose.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/recipe.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/recipe_brief.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/recipe_explain.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/recipe_forecast.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/recipe_lint.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/research.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/run_diagnose.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/runs.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/stream.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/stream_venue.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/studio_capabilities.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/transport.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/user_agent.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/v4.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/v4_artifacts.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/v4_catalog.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/v4_connected.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/v4_connections.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/v4_dataset_covers.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/v4_datasets.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/v4_handoff.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/v4_narrative.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/v4_query.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/v4_reader.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/v4_runs.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/v4_search.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/v4_secrets.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/v4_stream.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/v4_tables.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/vocabulary.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/ux/__init__.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/ux/attendance.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/ux/clarification.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/ux/cloud_auth.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/ux/commands/__init__.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/ux/commands/auth.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/ux/commands/clarify.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/ux/commands/login.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/ux/commands/whoami.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/ux/credential_native.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/ux/credential_store.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/ux/credentials.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/ux/login.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/ux/path_kind.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/ux/plain_file.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/ux/remediation.py +0 -0
- {mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/ux/render.py +0 -0
|
@@ -15,8 +15,9 @@ mr-data search inspect --recipe recipe.json --json
|
|
|
15
15
|
|
|
16
16
|
Local CLI help describes installed commands; it does not prove the deployed server serves them.
|
|
17
17
|
For the recipe-target probe above, read JSON refusals from stderr: `schema_version` is
|
|
18
|
-
`mr-data-error.v1`, `code` is the typed discriminator, and `error` is the detail.
|
|
19
|
-
|
|
18
|
+
`mr-data-error.v1`, `code` is the typed discriminator, and `error` is the detail. Cloud refusals
|
|
19
|
+
also expose `http_status`, `request_id`, `detail` and `retry_after_seconds` when supplied;
|
|
20
|
+
Studio inspection refusals retain their typed code. Treat `code: THIN_NOT_FOUND` as absent search
|
|
20
21
|
registration support only when `error` begins exactly with
|
|
21
22
|
`Studio has no such resource for /v4/search/recipe-inspection`; the CLI maps this route's HTTP 404
|
|
22
23
|
that way. An explicit `code: THIN_SEARCH_CAPABILITY_UNAVAILABLE` also states a capability limit.
|
|
@@ -141,3 +142,28 @@ an exact filter.
|
|
|
141
142
|
|
|
142
143
|
This workflow opts in newly authored recipes only. It does not migrate old datasets, reauthor users'
|
|
143
144
|
existing recipes, launch a full data rebuild or imply successful indexing of every table.
|
|
145
|
+
|
|
146
|
+
## Diagnose preparation and query a published table
|
|
147
|
+
|
|
148
|
+
`preparation_state: unavailable` can mean a never-built table, a failed or cancelled job,
|
|
149
|
+
or an incompatible specification. Keep `job_id` from the search build receipt and run
|
|
150
|
+
`mr-data search status --job JOB_ID --json` to inspect the job's status and failure.
|
|
151
|
+
Studio is adding `preparation_detail`; print it when present rather than inferring a reason
|
|
152
|
+
from `unavailable`. Table status passes this additive field through unchanged.
|
|
153
|
+
|
|
154
|
+
For a published table, first run `mr-data public schema TABLE_ID --json`.
|
|
155
|
+
The table schema's `capabilities.search` contains `table_version_id`, `spec_digest`,
|
|
156
|
+
`keyword_columns`, `semantic_columns`, and optional stored `lexical`/`semantic` preparation values.
|
|
157
|
+
Use `keyword_columns` for `search.columns`; top-level `columns` is the non-empty output projection.
|
|
158
|
+
The following lexical example uses a syntactically valid illustrative digest:
|
|
159
|
+
|
|
160
|
+
```sh
|
|
161
|
+
mr-data public query TABLE_ID --body '{"columns":["title"],"search":{"text":"example","columns":["title"],"spec_digest":"sha256:0000000000000000000000000000000000000000000000000000000000000000","mode":"lexical"},"limit":10}' --json
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Replace the illustrative columns and digest with the actual schema values. Hybrid mode additionally
|
|
165
|
+
needs `generation_digest` (`sha256:` plus 64 lowercase hex digits) from readiness/explain;
|
|
166
|
+
it is not in `capabilities.search`. Omit it for this lexical example. Public query prints
|
|
167
|
+
Cloud stage durations in milliseconds under `result.timings` when Server-Timing is present,
|
|
168
|
+
and reports HTTP status, request id and retry timing. Keep refusal `detail` with the request id.
|
|
169
|
+
Missing timing metadata does not establish that a stage did no work.
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/router.py
RENAMED
|
@@ -888,7 +888,10 @@ def _hosted(command: str, arguments: Sequence[str], *, as_json: bool) -> int:
|
|
|
888
888
|
as_json=as_json or parsed.json,
|
|
889
889
|
retry_after_seconds=getattr(refusal, "retry_after_seconds", None),
|
|
890
890
|
details=_refusal_details(refusal),
|
|
891
|
-
extra={
|
|
891
|
+
extra={
|
|
892
|
+
**getattr(refusal, "cloud_metadata", {}),
|
|
893
|
+
**({"sessions": sessions} if sessions else {}),
|
|
894
|
+
},
|
|
892
895
|
)
|
|
893
896
|
except Exception as error:
|
|
894
897
|
code = getattr(error, "code", None)
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/session.py
RENAMED
|
@@ -17,6 +17,7 @@ recorded production failures on 2026-08-20.
|
|
|
17
17
|
from __future__ import annotations
|
|
18
18
|
|
|
19
19
|
import json
|
|
20
|
+
import math
|
|
20
21
|
import re
|
|
21
22
|
import time
|
|
22
23
|
from collections.abc import Callable, Mapping
|
|
@@ -523,8 +524,59 @@ def stated_sentence(value: Any) -> str | None:
|
|
|
523
524
|
return stated
|
|
524
525
|
|
|
525
526
|
|
|
527
|
+
def _cloud_sentence(value: Any) -> str | None:
|
|
528
|
+
stated = stated_sentence(value)
|
|
529
|
+
if stated is None:
|
|
530
|
+
return None
|
|
531
|
+
# Refusal prose must never echo bearer/device tokens or URLs (including signed URLs).
|
|
532
|
+
stated = re.sub(r"https?://\S+", "[redacted URL]", stated, flags=re.IGNORECASE)
|
|
533
|
+
stated = re.sub(r"mr_(?:cli|use)_[A-Za-z0-9_-]+", "[redacted token]", stated)
|
|
534
|
+
stated = re.sub(r"(?i)bearer\s+\S+", "Bearer [redacted token]", stated)
|
|
535
|
+
return stated
|
|
536
|
+
|
|
537
|
+
|
|
538
|
+
def cloud_response_metadata(status: int, parsed: Any, headers: Mapping[str, str]) -> dict[str, Any]:
|
|
539
|
+
"""Only bounded diagnostic fields, never arbitrary response headers or authority."""
|
|
540
|
+
normalized = {key.lower(): value for key, value in headers.items()}
|
|
541
|
+
metadata: dict[str, Any] = {"http_status": status}
|
|
542
|
+
for request_id in (
|
|
543
|
+
normalized.get("x-request-id"),
|
|
544
|
+
parsed.get("request_id") if isinstance(parsed, dict) else None,
|
|
545
|
+
):
|
|
546
|
+
if (
|
|
547
|
+
isinstance(request_id, str)
|
|
548
|
+
and re.fullmatch(r"[A-Za-z0-9_.:-]{1,128}", request_id)
|
|
549
|
+
and not request_id.startswith("mr_")
|
|
550
|
+
):
|
|
551
|
+
metadata["request_id"] = request_id
|
|
552
|
+
break
|
|
553
|
+
raw_retry = normalized.get("retry-after", "")
|
|
554
|
+
if isinstance(raw_retry, str) and re.fullmatch(r"[0-9]{1,4}", raw_retry.strip()):
|
|
555
|
+
seconds = int(raw_retry.strip())
|
|
556
|
+
if 0 <= seconds <= 3600:
|
|
557
|
+
metadata["retry_after_seconds"] = seconds
|
|
558
|
+
timings: dict[str, float] = {}
|
|
559
|
+
for metric in normalized.get("server-timing", "")[:8192].split(",")[:64]:
|
|
560
|
+
match = re.fullmatch(
|
|
561
|
+
r"\s*([A-Za-z][A-Za-z0-9_-]{0,63})\s*;\s*dur=([0-9]+(?:\.[0-9]+)?)(?:\s*;.*)?\s*",
|
|
562
|
+
metric,
|
|
563
|
+
)
|
|
564
|
+
if match:
|
|
565
|
+
duration = float(match[2])
|
|
566
|
+
if math.isfinite(duration):
|
|
567
|
+
timings[match[1]] = duration
|
|
568
|
+
if timings:
|
|
569
|
+
metadata["timings"] = timings
|
|
570
|
+
return metadata
|
|
571
|
+
|
|
572
|
+
|
|
526
573
|
def cloud_refusal(
|
|
527
|
-
status: int,
|
|
574
|
+
status: int,
|
|
575
|
+
parsed: Any,
|
|
576
|
+
*,
|
|
577
|
+
act: str,
|
|
578
|
+
absent: str | None = None,
|
|
579
|
+
headers: Mapping[str, str] | None = None,
|
|
528
580
|
) -> ThinLaneError:
|
|
529
581
|
"""One Cloud refusal, folded the way ``runs._studio_refusal`` folds Studio's.
|
|
530
582
|
|
|
@@ -564,7 +616,7 @@ def cloud_refusal(
|
|
|
564
616
|
stated = parsed.get("code") if isinstance(parsed, dict) else None
|
|
565
617
|
named = stated if isinstance(stated, str) and CLOUD_REFUSAL_CODE.fullmatch(stated) else None
|
|
566
618
|
said = (
|
|
567
|
-
|
|
619
|
+
_cloud_sentence(parsed.get("error")) if named is None and isinstance(parsed, dict) else None
|
|
568
620
|
)
|
|
569
621
|
if status in {401, 403}:
|
|
570
622
|
if named:
|
|
@@ -588,7 +640,16 @@ def cloud_refusal(
|
|
|
588
640
|
refusal = ThinLaneError(
|
|
589
641
|
"THIN_CLOUD_REFUSED", f"{detail}. Cloud said: {said}" if said else detail
|
|
590
642
|
)
|
|
591
|
-
|
|
643
|
+
detail = _cloud_sentence(parsed.get("detail")) if isinstance(parsed, dict) else None
|
|
644
|
+
if detail:
|
|
645
|
+
refusal.detail += f". Cloud detail: {detail}"
|
|
646
|
+
refusal.args = (f"{refusal.code}: {refusal.detail}",)
|
|
647
|
+
refusal.cloud_metadata = cloud_response_metadata(status, parsed, headers or {})
|
|
648
|
+
if detail:
|
|
649
|
+
refusal.cloud_metadata["detail"] = detail
|
|
650
|
+
for field, value in refusal.cloud_metadata.items():
|
|
651
|
+
if field != "detail":
|
|
652
|
+
setattr(refusal, field, value)
|
|
592
653
|
return refusal
|
|
593
654
|
|
|
594
655
|
|
|
@@ -613,6 +674,7 @@ class CloudClient:
|
|
|
613
674
|
self._credentials = credentials
|
|
614
675
|
self._origin = service_origin(credentials.cloud_url, "Cloud URL", allow_loopback_http=False)
|
|
615
676
|
self._transport = transport or UrlLibTransport()
|
|
677
|
+
self.response_metadata: dict[str, Any] = {}
|
|
616
678
|
|
|
617
679
|
@property
|
|
618
680
|
def cloud_url(self) -> str:
|
|
@@ -661,7 +723,7 @@ class CloudClient:
|
|
|
661
723
|
if body is not None:
|
|
662
724
|
headers["Content-Type"] = "application/json"
|
|
663
725
|
encoded = json.dumps(dict(body), separators=(",", ":")).encode("utf-8")
|
|
664
|
-
status, raw,
|
|
726
|
+
status, raw, response_headers = self._transport.request(
|
|
665
727
|
method,
|
|
666
728
|
f"{self._origin}{path}",
|
|
667
729
|
headers,
|
|
@@ -676,8 +738,9 @@ class CloudClient:
|
|
|
676
738
|
)
|
|
677
739
|
except CanonicalJSONError:
|
|
678
740
|
parsed = None
|
|
741
|
+
self.response_metadata = cloud_response_metadata(status, parsed, response_headers)
|
|
679
742
|
if status not in expected:
|
|
680
|
-
raise cloud_refusal(status, parsed, act=act, absent=absent)
|
|
743
|
+
raise cloud_refusal(status, parsed, act=act, absent=absent, headers=response_headers)
|
|
681
744
|
if not isinstance(parsed, dict):
|
|
682
745
|
raise ThinLaneError(
|
|
683
746
|
"THIN_RESPONSE_INVALID",
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/v4_public.py
RENAMED
|
@@ -39,6 +39,7 @@ from mostlyright.data_harness.thin.session import (
|
|
|
39
39
|
MAX_TOKEN_RESPONSE_BYTES,
|
|
40
40
|
CloudClient,
|
|
41
41
|
cloud_refusal,
|
|
42
|
+
cloud_response_metadata,
|
|
42
43
|
require_device_key,
|
|
43
44
|
stated_sentence,
|
|
44
45
|
)
|
|
@@ -193,7 +194,6 @@ def declare_arguments(parser: argparse.ArgumentParser) -> None:
|
|
|
193
194
|
),
|
|
194
195
|
)
|
|
195
196
|
|
|
196
|
-
|
|
197
197
|
parser.add_argument(
|
|
198
198
|
"--body",
|
|
199
199
|
default=None,
|
|
@@ -287,8 +287,10 @@ class PublicCatalogClient:
|
|
|
287
287
|
)
|
|
288
288
|
error = parsed.get("error")
|
|
289
289
|
detail = parsed.get("detail") if isinstance(parsed.get("detail"), str) else None
|
|
290
|
-
code =
|
|
291
|
-
"
|
|
290
|
+
code = (
|
|
291
|
+
f"THIN_CLOUD_{error}".upper()
|
|
292
|
+
if isinstance(error, str) and error
|
|
293
|
+
else ("THIN_CLOUD_REFUSED")
|
|
292
294
|
)
|
|
293
295
|
message = detail or f"Cloud refused to {act} (HTTP {status})"
|
|
294
296
|
refusal = ThinLaneError(code, message)
|
|
@@ -471,9 +473,7 @@ def _search_hit(dataset: Mapping[str, Any]) -> dict[str, Any]:
|
|
|
471
473
|
"id": dataset.get("id"),
|
|
472
474
|
"slug": dataset.get("slug"),
|
|
473
475
|
"title": dataset.get("title"),
|
|
474
|
-
"summary": (
|
|
475
|
-
f"{summary[: SEARCH_SUMMARY_LIMIT - 1].rstrip()}…" if cut else summary
|
|
476
|
-
),
|
|
476
|
+
"summary": (f"{summary[: SEARCH_SUMMARY_LIMIT - 1].rstrip()}…" if cut else summary),
|
|
477
477
|
"topics": list(dataset.get("topics") or []),
|
|
478
478
|
"publisher": _publisher(publisher),
|
|
479
479
|
"published_at": dataset.get("published_at"),
|
|
@@ -861,7 +861,6 @@ def _fetch(args: argparse.Namespace, client: PublicCatalogClient) -> dict[str, A
|
|
|
861
861
|
}
|
|
862
862
|
|
|
863
863
|
|
|
864
|
-
|
|
865
864
|
CLOUD_PUBLIC_TABLE_QUERY_PATH = "/api/cli/public/tables/{table_id}/query"
|
|
866
865
|
CLOUD_PUBLIC_TABLE_DOWNLOAD_URL_PATH = "/api/cli/public/tables/{table_id}/download-url"
|
|
867
866
|
QUERY_SCHEMA = f"{THIN_SCHEMA_PREFIX}-v4-public-query.v1"
|
|
@@ -885,8 +884,15 @@ MAX_PUBLIC_QUERY_RESPONSE_MEMBERS = (
|
|
|
885
884
|
class PublicQueryClient(CloudClient):
|
|
886
885
|
"""Authenticated public table query + download-url over the device-key client."""
|
|
887
886
|
|
|
887
|
+
def __init__(self, credentials, *, transport=None) -> None:
|
|
888
|
+
# Let Cloud's gateway deadline return its own refusal and request id first.
|
|
889
|
+
super().__init__(credentials, transport=transport)
|
|
890
|
+
self._query_client = CloudClient(
|
|
891
|
+
credentials, transport=transport or UrlLibTransport(timeout=150.0)
|
|
892
|
+
)
|
|
893
|
+
|
|
888
894
|
def query_table(self, table_id: str, body: Mapping[str, Any]) -> dict[str, Any]:
|
|
889
|
-
|
|
895
|
+
answer = self._query_client.call(
|
|
890
896
|
"POST",
|
|
891
897
|
CLOUD_PUBLIC_TABLE_QUERY_PATH.format(table_id=table_id),
|
|
892
898
|
act="query a public table",
|
|
@@ -897,6 +903,9 @@ class PublicQueryClient(CloudClient):
|
|
|
897
903
|
max_members=MAX_PUBLIC_QUERY_RESPONSE_MEMBERS,
|
|
898
904
|
)
|
|
899
905
|
|
|
906
|
+
self.response_metadata = self._query_client.response_metadata
|
|
907
|
+
return answer
|
|
908
|
+
|
|
900
909
|
def download_url(self, table_id: str) -> dict[str, Any]:
|
|
901
910
|
"""Read download instructions; keep download_not_enabled distinct from missing table.
|
|
902
911
|
|
|
@@ -911,7 +920,7 @@ class PublicQueryClient(CloudClient):
|
|
|
911
920
|
"Accept": "application/json",
|
|
912
921
|
"Authorization": f"Bearer {self._credentials.raw_key}",
|
|
913
922
|
}
|
|
914
|
-
status, raw,
|
|
923
|
+
status, raw, response_headers = self._transport.request(
|
|
915
924
|
"GET",
|
|
916
925
|
f"{self.cloud_url}{path}",
|
|
917
926
|
headers,
|
|
@@ -941,6 +950,7 @@ class PublicQueryClient(CloudClient):
|
|
|
941
950
|
"THIN_CLOUD_DOWNLOAD_NOT_ENABLED",
|
|
942
951
|
f"Cloud refused to {act} (download_not_enabled). Cloud said: {said}",
|
|
943
952
|
)
|
|
953
|
+
refusal.cloud_metadata = cloud_response_metadata(404, parsed, response_headers)
|
|
944
954
|
refusal.http_status = 404 # type: ignore[attr-defined]
|
|
945
955
|
raise refusal
|
|
946
956
|
raise cloud_refusal(
|
|
@@ -948,6 +958,7 @@ class PublicQueryClient(CloudClient):
|
|
|
948
958
|
parsed,
|
|
949
959
|
act=act,
|
|
950
960
|
absent="no public table has that id",
|
|
961
|
+
headers=response_headers,
|
|
951
962
|
)
|
|
952
963
|
|
|
953
964
|
|
|
@@ -993,12 +1004,16 @@ def _query(args: argparse.Namespace, client: Any = None) -> dict[str, Any]:
|
|
|
993
1004
|
body = _read_query_body(args)
|
|
994
1005
|
selected = _auth_query_client(client if isinstance(client, PublicQueryClient) else None)
|
|
995
1006
|
answer = selected.query_table(table_id, body)
|
|
1007
|
+
metadata = getattr(selected, "response_metadata", {})
|
|
1008
|
+
if "timings" in metadata:
|
|
1009
|
+
answer = {**answer, "timings": metadata["timings"]}
|
|
996
1010
|
return {
|
|
997
1011
|
"schema_version": QUERY_SCHEMA,
|
|
998
1012
|
"status": "public_table_queried",
|
|
999
1013
|
"lane": "hosted",
|
|
1000
1014
|
"table_id": table_id,
|
|
1001
1015
|
"result": answer,
|
|
1016
|
+
**{key: value for key, value in metadata.items() if key != "timings"},
|
|
1002
1017
|
"next_step": _NEXT["public_table_queried"],
|
|
1003
1018
|
}
|
|
1004
1019
|
|
|
@@ -1061,16 +1076,20 @@ def public(
|
|
|
1061
1076
|
"THIN_REQUEST_INVALID",
|
|
1062
1077
|
f"--cursor applies to public search, not public {action}",
|
|
1063
1078
|
)
|
|
1064
|
-
if
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1079
|
+
if (
|
|
1080
|
+
action
|
|
1081
|
+
in {
|
|
1082
|
+
"show",
|
|
1083
|
+
"tables",
|
|
1084
|
+
"schema",
|
|
1085
|
+
"sample",
|
|
1086
|
+
"fetch",
|
|
1087
|
+
"lookup",
|
|
1088
|
+
"query",
|
|
1089
|
+
"download-url",
|
|
1090
|
+
}
|
|
1091
|
+
and not args.target
|
|
1092
|
+
):
|
|
1074
1093
|
needed = {
|
|
1075
1094
|
"show": "a dataset slug",
|
|
1076
1095
|
"tables": "a dataset slug",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/agents/openai.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/boundaries.md
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/commands.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/live-run.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/one-install.md
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/promote.md
RENAMED
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/readers.md
RENAMED
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/receipts.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/sources.md
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/skills/mr-data-build/references/transforms.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/__init__.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/agent_protocol.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/canonical.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/formats.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/key_seam.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/page_coverage.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/session_probes.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/skill_assets.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/table_manifest.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/__init__.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/acquire.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/activity.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/approvals.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/categories.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/commands.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/download.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/narrative.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/parity.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/probe.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/propose.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/recipe.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/research.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/runs.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/stream.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/transport.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/user_agent.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/v4.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/v4_catalog.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/v4_handoff.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/v4_query.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/v4_reader.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/v4_runs.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/v4_search.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/v4_secrets.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/v4_stream.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/v4_tables.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/thin/vocabulary.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/ux/__init__.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/ux/attendance.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/ux/cloud_auth.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/ux/credentials.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/ux/login.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/ux/path_kind.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/ux/plain_file.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/ux/remediation.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.9 → mostlyright_data-0.29.10}/src/mostlyright/data_harness/ux/render.py
RENAMED
|
File without changes
|