hushscript 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.
- hushscript/__init__.py +97 -0
- hushscript/_client.py +687 -0
- hushscript/_clock.py +36 -0
- hushscript/_config.py +139 -0
- hushscript/_errors.py +563 -0
- hushscript/_guard.py +61 -0
- hushscript/_http.py +624 -0
- hushscript/_json.py +55 -0
- hushscript/_log.py +155 -0
- hushscript/_models.py +144 -0
- hushscript/_pacing.py +51 -0
- hushscript/_redact.py +140 -0
- hushscript/_response.py +67 -0
- hushscript/_retry.py +205 -0
- hushscript/_shape.py +197 -0
- hushscript/_shapes.py +248 -0
- hushscript/_version.py +1 -0
- hushscript/format.py +224 -0
- hushscript/generated/__init__.py +8 -0
- hushscript/generated/api/__init__.py +1 -0
- hushscript/generated/api/default/__init__.py +1 -0
- hushscript/generated/api/default/buy_minutes.py +248 -0
- hushscript/generated/api/default/claim_agent_account.py +238 -0
- hushscript/generated/api/default/complete_upload.py +238 -0
- hushscript/generated/api/default/create_agent_account_signup.py +261 -0
- hushscript/generated/api/default/create_setup_session.py +244 -0
- hushscript/generated/api/default/create_upload.py +225 -0
- hushscript/generated/api/default/get_account.py +169 -0
- hushscript/generated/api/default/get_job.py +198 -0
- hushscript/generated/api/default/get_org.py +169 -0
- hushscript/generated/api/default/get_transcript.py +226 -0
- hushscript/generated/api/default/get_transcription_context.py +173 -0
- hushscript/generated/api/default/get_upload_part_urls.py +246 -0
- hushscript/generated/api/default/heartbeat_upload.py +197 -0
- hushscript/generated/api/default/lift_transcript_hold.py +206 -0
- hushscript/generated/api/default/list_credit_ledger.py +229 -0
- hushscript/generated/api/default/list_deleted_transcripts.py +237 -0
- hushscript/generated/api/default/list_holds.py +233 -0
- hushscript/generated/api/default/list_jobs.py +249 -0
- hushscript/generated/api/default/list_org_audit.py +221 -0
- hushscript/generated/api/default/list_org_invoices.py +221 -0
- hushscript/generated/api/default/list_org_ledger.py +221 -0
- hushscript/generated/api/default/list_org_matters.py +247 -0
- hushscript/generated/api/default/list_org_members.py +221 -0
- hushscript/generated/api/default/list_org_transcripts.py +233 -0
- hushscript/generated/api/default/list_packs.py +169 -0
- hushscript/generated/api/default/list_saved_cards.py +169 -0
- hushscript/generated/api/default/list_transactions.py +225 -0
- hushscript/generated/api/default/list_transcripts.py +225 -0
- hushscript/generated/api/default/org_audit_csv.py +163 -0
- hushscript/generated/api/default/org_ledger_csv.py +163 -0
- hushscript/generated/api/default/org_usage_report.py +247 -0
- hushscript/generated/api/default/org_usage_report_csv.py +229 -0
- hushscript/generated/api/default/patch_org_member.py +237 -0
- hushscript/generated/api/default/place_transcript_hold.py +206 -0
- hushscript/generated/api/default/rotate_agent_credentials.py +177 -0
- hushscript/generated/api/default/schedule_org_custody.py +215 -0
- hushscript/generated/api/default/set_default_card.py +223 -0
- hushscript/generated/api/default/upload_part.py +249 -0
- hushscript/generated/catalog.py +138 -0
- hushscript/generated/client.py +282 -0
- hushscript/generated/errors.py +16 -0
- hushscript/generated/hints.py +28 -0
- hushscript/generated/models/__init__.py +193 -0
- hushscript/generated/models/account_response.py +114 -0
- hushscript/generated/models/active_hold.py +88 -0
- hushscript/generated/models/active_hold_kind.py +18 -0
- hushscript/generated/models/agent_claim_request.py +61 -0
- hushscript/generated/models/agent_claim_response.py +85 -0
- hushscript/generated/models/agent_credentials_rotate_response.py +101 -0
- hushscript/generated/models/agent_signup_request.py +118 -0
- hushscript/generated/models/agent_signup_request_agent.py +80 -0
- hushscript/generated/models/agent_signup_response.py +111 -0
- hushscript/generated/models/buy_minutes_body.py +89 -0
- hushscript/generated/models/card.py +132 -0
- hushscript/generated/models/cards_response.py +90 -0
- hushscript/generated/models/complete_upload_body.py +107 -0
- hushscript/generated/models/complete_upload_body_parts_type_0_item.py +69 -0
- hushscript/generated/models/context_dictionary.py +143 -0
- hushscript/generated/models/context_prompt_preset.py +118 -0
- hushscript/generated/models/create_setup_session_body.py +62 -0
- hushscript/generated/models/create_upload_body.py +254 -0
- hushscript/generated/models/create_upload_body_transcription_options_type_0.py +178 -0
- hushscript/generated/models/credit_ledger_entry.py +113 -0
- hushscript/generated/models/credit_ledger_response.py +90 -0
- hushscript/generated/models/deleted_transcript.py +148 -0
- hushscript/generated/models/deleted_transcript_cause.py +18 -0
- hushscript/generated/models/deleted_transcript_receipt_type_0.py +107 -0
- hushscript/generated/models/deleted_transcript_receipt_type_0_items_item.py +69 -0
- hushscript/generated/models/deleted_transcripts_response.py +90 -0
- hushscript/generated/models/dictionary_entry.py +123 -0
- hushscript/generated/models/dictionary_entry_category.py +37 -0
- hushscript/generated/models/error.py +155 -0
- hushscript/generated/models/error_details.py +94 -0
- hushscript/generated/models/get_upload_part_urls_response_200_type_0.py +108 -0
- hushscript/generated/models/heartbeat_upload_response_200.py +61 -0
- hushscript/generated/models/holds_response.py +90 -0
- hushscript/generated/models/job.py +309 -0
- hushscript/generated/models/job_failure_kind_type_1.py +16 -0
- hushscript/generated/models/job_failure_kind_type_2_type_1.py +16 -0
- hushscript/generated/models/job_failure_kind_type_3_type_1.py +16 -0
- hushscript/generated/models/job_list.py +90 -0
- hushscript/generated/models/lift_transcript_hold_response_200.py +61 -0
- hushscript/generated/models/list_jobs_active.py +17 -0
- hushscript/generated/models/list_org_matters_status.py +16 -0
- hushscript/generated/models/options_summary.py +135 -0
- hushscript/generated/models/org_audit_entry.py +105 -0
- hushscript/generated/models/org_audit_response.py +90 -0
- hushscript/generated/models/org_invoice.py +175 -0
- hushscript/generated/models/org_invoices_response.py +90 -0
- hushscript/generated/models/org_ledger_entry.py +155 -0
- hushscript/generated/models/org_ledger_response.py +90 -0
- hushscript/generated/models/org_matter.py +79 -0
- hushscript/generated/models/org_matter_status.py +16 -0
- hushscript/generated/models/org_matters_response.py +75 -0
- hushscript/generated/models/org_member.py +123 -0
- hushscript/generated/models/org_members_response.py +90 -0
- hushscript/generated/models/org_summary_response.py +482 -0
- hushscript/generated/models/org_transcript.py +103 -0
- hushscript/generated/models/org_transcripts_response.py +90 -0
- hushscript/generated/models/org_usage_report_csv_group_by.py +17 -0
- hushscript/generated/models/org_usage_report_group_by.py +17 -0
- hushscript/generated/models/org_usage_response.py +112 -0
- hushscript/generated/models/org_usage_response_group_by.py +17 -0
- hushscript/generated/models/org_usage_row.py +86 -0
- hushscript/generated/models/pack.py +107 -0
- hushscript/generated/models/packs_response.py +75 -0
- hushscript/generated/models/patch_org_member_body.py +102 -0
- hushscript/generated/models/patch_org_member_response_200.py +61 -0
- hushscript/generated/models/place_transcript_hold_response_200.py +61 -0
- hushscript/generated/models/presigned_part_url.py +69 -0
- hushscript/generated/models/purchase_response.py +76 -0
- hushscript/generated/models/schedule_org_custody_body.py +66 -0
- hushscript/generated/models/schedule_org_custody_body_custody.py +17 -0
- hushscript/generated/models/schedule_org_custody_response_200.py +69 -0
- hushscript/generated/models/set_default_card_body.py +61 -0
- hushscript/generated/models/set_default_card_response_200.py +61 -0
- hushscript/generated/models/setup_session_response.py +77 -0
- hushscript/generated/models/transaction.py +183 -0
- hushscript/generated/models/transactions_response.py +98 -0
- hushscript/generated/models/transcript_detail.py +194 -0
- hushscript/generated/models/transcript_detail_speaker_names.py +47 -0
- hushscript/generated/models/transcript_envelope.py +89 -0
- hushscript/generated/models/transcript_envelope_translations.py +62 -0
- hushscript/generated/models/transcript_language.py +75 -0
- hushscript/generated/models/transcript_list.py +90 -0
- hushscript/generated/models/transcript_list_row.py +152 -0
- hushscript/generated/models/transcript_list_row_insights_state.py +20 -0
- hushscript/generated/models/transcription_context_response.py +95 -0
- hushscript/generated/models/upload_complete_response.py +100 -0
- hushscript/generated/models/upload_create_response.py +148 -0
- hushscript/generated/models/upload_create_response_funding.py +16 -0
- hushscript/generated/models/upload_create_response_upload_type_0.py +108 -0
- hushscript/generated/models/upload_limits.py +86 -0
- hushscript/generated/models/upload_part_response_200.py +69 -0
- hushscript/generated/models/utterance.py +85 -0
- hushscript/generated/scopes.py +42 -0
- hushscript/generated/types.py +54 -0
- hushscript/money.py +79 -0
- hushscript/paginate.py +78 -0
- hushscript/py.typed +0 -0
- hushscript/resources/__init__.py +1 -0
- hushscript/resources/_params.py +33 -0
- hushscript/resources/account.py +121 -0
- hushscript/resources/agent.py +421 -0
- hushscript/resources/billing.py +567 -0
- hushscript/resources/jobs.py +105 -0
- hushscript/resources/transcripts.py +209 -0
- hushscript/transcribe/__init__.py +1 -0
- hushscript/transcribe/apipeline.py +234 -0
- hushscript/transcribe/aupload.py +197 -0
- hushscript/transcribe/heartbeat.py +78 -0
- hushscript/transcribe/pipeline.py +312 -0
- hushscript/transcribe/preflight.py +272 -0
- hushscript/transcribe/probe.py +185 -0
- hushscript/transcribe/resume.py +115 -0
- hushscript/transcribe/segment.py +23 -0
- hushscript/transcribe/session.py +34 -0
- hushscript/transcribe/sniff.py +30 -0
- hushscript/transcribe/source.py +218 -0
- hushscript/transcribe/upload.py +498 -0
- hushscript/transcribe/wait.py +124 -0
- hushscript/transcript.py +197 -0
- hushscript-1.0.0.dist-info/METADATA +502 -0
- hushscript-1.0.0.dist-info/RECORD +187 -0
- hushscript-1.0.0.dist-info/WHEEL +4 -0
- hushscript-1.0.0.dist-info/licenses/LICENSE +21 -0
hushscript/_clock.py
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
import time
|
|
5
|
+
from typing import TYPE_CHECKING, Protocol
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
import threading
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Clock(Protocol):
|
|
12
|
+
"""Time source for pacing, backoff and polling; tests and the runner inject their own."""
|
|
13
|
+
|
|
14
|
+
def now(self) -> float: ...
|
|
15
|
+
|
|
16
|
+
def sleep(self, seconds: float) -> None: ...
|
|
17
|
+
|
|
18
|
+
def wait(self, stop: threading.Event, seconds: float) -> bool:
|
|
19
|
+
"""Sleeps up to `seconds` but wakes as soon as `stop` is set; True when it was set."""
|
|
20
|
+
...
|
|
21
|
+
|
|
22
|
+
async def asleep(self, seconds: float) -> None: ...
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class SystemClock:
|
|
26
|
+
def now(self) -> float:
|
|
27
|
+
return time.monotonic()
|
|
28
|
+
|
|
29
|
+
def sleep(self, seconds: float) -> None:
|
|
30
|
+
time.sleep(seconds)
|
|
31
|
+
|
|
32
|
+
def wait(self, stop: threading.Event, seconds: float) -> bool:
|
|
33
|
+
return stop.wait(seconds)
|
|
34
|
+
|
|
35
|
+
async def asleep(self, seconds: float) -> None:
|
|
36
|
+
await asyncio.sleep(seconds)
|
hushscript/_config.py
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from typing import TYPE_CHECKING, Final
|
|
6
|
+
from urllib.parse import urlsplit
|
|
7
|
+
|
|
8
|
+
from ._errors import ConfigurationError
|
|
9
|
+
from ._log import LOG_LEVELS
|
|
10
|
+
from ._redact import Credentials
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from collections.abc import Mapping
|
|
14
|
+
|
|
15
|
+
DEFAULT_BASE_URL: Final = "https://api.hushscript.com"
|
|
16
|
+
DEFAULT_TIMEOUT: Final = 60.0
|
|
17
|
+
PART_TIMEOUT: Final = 300.0
|
|
18
|
+
DEFAULT_MAX_RETRIES: Final = 3
|
|
19
|
+
TOKEN_ENV: Final = "HUSHSCRIPT_TOKEN" # noqa: S105 # the name of an environment variable
|
|
20
|
+
BASE_URL_ENV: Final = "HUSHSCRIPT_BASE_URL"
|
|
21
|
+
LOG_ENV: Final = "HUSHSCRIPT_LOG"
|
|
22
|
+
TOKEN_PREFIX: Final = "hsr" # noqa: S105 # the token family prefix, not a secret
|
|
23
|
+
PRINTABLE_FIRST: Final = 0x21
|
|
24
|
+
PRINTABLE_LAST: Final = 0x7E
|
|
25
|
+
LOOPBACK_HOSTS: Final = frozenset({"localhost", "127.0.0.1", "::1"})
|
|
26
|
+
|
|
27
|
+
SETUP_HINT: Final = (
|
|
28
|
+
"Set HUSHSCRIPT_TOKEN or pass a token. Create one in the Hushscript app: "
|
|
29
|
+
"Account → MCP (app.hushscript.com/account/mcp)."
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@dataclass(frozen=True, slots=True)
|
|
34
|
+
class Config:
|
|
35
|
+
credentials: Credentials
|
|
36
|
+
base_url: str
|
|
37
|
+
timeout: float
|
|
38
|
+
max_retries: int
|
|
39
|
+
log_level: str
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _set(value: str | None) -> str | None:
|
|
43
|
+
"""R85: None, "" and whitespace-only text all mean "not set"."""
|
|
44
|
+
return value if value is not None and value.strip() else None
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _validate_base_url(raw: str) -> str:
|
|
48
|
+
parts = urlsplit(raw)
|
|
49
|
+
if parts.path not in {"", "/"} or "?" in raw or "#" in raw:
|
|
50
|
+
# Requests are classified by their path relative to the base URL (spec 7.4), so it has none.
|
|
51
|
+
raise ConfigurationError("base_url must not have a path, query or fragment.")
|
|
52
|
+
host = parts.hostname or ""
|
|
53
|
+
secure = parts.scheme == "https"
|
|
54
|
+
loopback = parts.scheme == "http" and host in LOOPBACK_HOSTS
|
|
55
|
+
if not (secure or loopback) or not host or parts.username or parts.password:
|
|
56
|
+
raise ConfigurationError(
|
|
57
|
+
"base_url must be https://, or http:// to localhost, 127.0.0.1 or [::1]."
|
|
58
|
+
)
|
|
59
|
+
return raw.rstrip("/")
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def _is_positive_number(value: object) -> bool:
|
|
63
|
+
return isinstance(value, (int, float)) and not isinstance(value, bool) and value > 0
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def _is_non_negative_int(value: object) -> bool:
|
|
67
|
+
return isinstance(value, int) and not isinstance(value, bool) and value >= 0
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def acceptable_token(token: str) -> bool:
|
|
71
|
+
"""The check every token passes, at construction and after a claim or a rotation: printable
|
|
72
|
+
ASCII only, and the `hsr` prefix."""
|
|
73
|
+
return token.startswith(TOKEN_PREFIX) and all(
|
|
74
|
+
PRINTABLE_FIRST <= ord(char) <= PRINTABLE_LAST for char in token
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def resolve_tokenless_config( # mirrors the keyword surface of the static agent calls
|
|
79
|
+
*,
|
|
80
|
+
base_url: str | None = None,
|
|
81
|
+
timeout: float = DEFAULT_TIMEOUT,
|
|
82
|
+
log_level: str | None = None,
|
|
83
|
+
env: Mapping[str, str] | None = None,
|
|
84
|
+
) -> Config:
|
|
85
|
+
"""The config of a call that needs no token: HUSHSCRIPT_TOKEN is neither read nor sent."""
|
|
86
|
+
environment = os.environ if env is None else env
|
|
87
|
+
resolved_url = _validate_base_url(
|
|
88
|
+
_set(base_url) or _set(environment.get(BASE_URL_ENV)) or DEFAULT_BASE_URL
|
|
89
|
+
)
|
|
90
|
+
if not _is_positive_number(timeout):
|
|
91
|
+
raise ConfigurationError("timeout must be a positive number of seconds.")
|
|
92
|
+
level = _set(log_level) or _set(environment.get(LOG_ENV)) or "off"
|
|
93
|
+
if level not in LOG_LEVELS:
|
|
94
|
+
raise ConfigurationError(f"log_level must be one of {', '.join(LOG_LEVELS)}.")
|
|
95
|
+
return Config(
|
|
96
|
+
credentials=Credentials(),
|
|
97
|
+
base_url=resolved_url,
|
|
98
|
+
timeout=float(timeout),
|
|
99
|
+
max_retries=0,
|
|
100
|
+
log_level=level,
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def resolve_config( # mirrors the public constructor
|
|
105
|
+
token: str | None = None,
|
|
106
|
+
*,
|
|
107
|
+
base_url: str | None = None,
|
|
108
|
+
timeout: float = DEFAULT_TIMEOUT,
|
|
109
|
+
max_retries: int = DEFAULT_MAX_RETRIES,
|
|
110
|
+
log_level: str | None = None,
|
|
111
|
+
env: Mapping[str, str] | None = None,
|
|
112
|
+
) -> Config:
|
|
113
|
+
environment = os.environ if env is None else env
|
|
114
|
+
chosen_token = _set(token) or _set(environment.get(TOKEN_ENV))
|
|
115
|
+
if chosen_token is None:
|
|
116
|
+
raise ConfigurationError("No Hushscript token was provided.", hint=SETUP_HINT)
|
|
117
|
+
resolved_token = chosen_token.strip()
|
|
118
|
+
if any(not PRINTABLE_FIRST <= ord(char) <= PRINTABLE_LAST for char in resolved_token):
|
|
119
|
+
# The message never echoes the token (spec 7.4).
|
|
120
|
+
raise ConfigurationError("The token contains control or non-printable characters.")
|
|
121
|
+
if not resolved_token.startswith(TOKEN_PREFIX):
|
|
122
|
+
raise ConfigurationError("This doesn't look like a Hushscript token.")
|
|
123
|
+
resolved_url = _validate_base_url(
|
|
124
|
+
_set(base_url) or _set(environment.get(BASE_URL_ENV)) or DEFAULT_BASE_URL
|
|
125
|
+
)
|
|
126
|
+
if not _is_positive_number(timeout):
|
|
127
|
+
raise ConfigurationError("timeout must be a positive number of seconds.")
|
|
128
|
+
if not _is_non_negative_int(max_retries):
|
|
129
|
+
raise ConfigurationError("max_retries must be a non-negative integer.")
|
|
130
|
+
level = _set(log_level) or _set(environment.get(LOG_ENV)) or "off"
|
|
131
|
+
if level not in LOG_LEVELS:
|
|
132
|
+
raise ConfigurationError(f"log_level must be one of {', '.join(LOG_LEVELS)}.")
|
|
133
|
+
return Config(
|
|
134
|
+
credentials=Credentials(resolved_token),
|
|
135
|
+
base_url=resolved_url,
|
|
136
|
+
timeout=float(timeout),
|
|
137
|
+
max_retries=max_retries,
|
|
138
|
+
log_level=level,
|
|
139
|
+
)
|