pinecall-runtime 0.1.6__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.
- pinecall/__init__.py +0 -0
- pinecall/channels/__init__.py +0 -0
- pinecall/channels/_chooser.py +45 -0
- pinecall/channels/offers.py +219 -0
- pinecall/channels/rooms.py +176 -0
- pinecall/channels/routes.py +275 -0
- pinecall/channels/telephony/__init__.py +0 -0
- pinecall/channels/telephony/_twilio.py +349 -0
- pinecall/channels/telephony/carrier.py +229 -0
- pinecall/channels/telephony/carrier_catalog.py +92 -0
- pinecall/channels/telephony/carriers.csv +41 -0
- pinecall/channels/telephony/dialing.py +419 -0
- pinecall/channels/telephony/firewall.py +58 -0
- pinecall/channels/telephony/hand_over.py +78 -0
- pinecall/channels/telephony/number_path.py +176 -0
- pinecall/channels/telephony/numbers.py +530 -0
- pinecall/channels/telephony/origination.py +77 -0
- pinecall/channels/telephony/sip.py +448 -0
- pinecall/channels/whatsapp.py +413 -0
- pinecall/cli/__init__.py +0 -0
- pinecall/cli/_archive.py +85 -0
- pinecall/cli/_drift.py +38 -0
- pinecall/cli/_facts.py +67 -0
- pinecall/cli/_load.py +433 -0
- pinecall/cli/_operator.py +626 -0
- pinecall/cli/_sessions.py +164 -0
- pinecall/cli/_traceback.py +95 -0
- pinecall/cli/_usage.py +34 -0
- pinecall/cli/main.py +521 -0
- pinecall/domain/__init__.py +0 -0
- pinecall/domain/agent.py +446 -0
- pinecall/domain/call.py +152 -0
- pinecall/domain/country_codes.py +32 -0
- pinecall/domain/errors.py +151 -0
- pinecall/domain/names.py +115 -0
- pinecall/domain/org.py +120 -0
- pinecall/domain/person.py +208 -0
- pinecall/domain/scope.py +21 -0
- pinecall/evals/__init__.py +0 -0
- pinecall/evals/_evidence.py +158 -0
- pinecall/evals/calibration.py +112 -0
- pinecall/evals/callers.py +160 -0
- pinecall/evals/case.py +327 -0
- pinecall/evals/checks.py +437 -0
- pinecall/evals/compliance.py +197 -0
- pinecall/evals/dataset.py +451 -0
- pinecall/evals/goldens.py +331 -0
- pinecall/evals/judges.py +525 -0
- pinecall/evals/runs.py +252 -0
- pinecall/evals/spoken.py +356 -0
- pinecall/fleet/__init__.py +0 -0
- pinecall/fleet/client.py +569 -0
- pinecall/fleet/demand.py +51 -0
- pinecall/fleet/heartbeat.py +194 -0
- pinecall/fleet/measures.py +157 -0
- pinecall/fleet/roster.py +232 -0
- pinecall/fleet/worlds.py +44 -0
- pinecall/gateway/__init__.py +0 -0
- pinecall/gateway/_call_setup.py +53 -0
- pinecall/gateway/_deps.py +556 -0
- pinecall/gateway/_gateway.py +75 -0
- pinecall/gateway/_served.py +396 -0
- pinecall/gateway/_sockets.py +444 -0
- pinecall/gateway/_streams.py +83 -0
- pinecall/gateway/_text_calls.py +182 -0
- pinecall/gateway/api/__init__.py +0 -0
- pinecall/gateway/api/accounts.py +324 -0
- pinecall/gateway/api/agents.py +150 -0
- pinecall/gateway/api/apps.py +478 -0
- pinecall/gateway/api/box.py +658 -0
- pinecall/gateway/api/calibration.py +58 -0
- pinecall/gateway/api/callbacks.py +105 -0
- pinecall/gateway/api/calls.py +655 -0
- pinecall/gateway/api/chat.py +223 -0
- pinecall/gateway/api/dataset.py +163 -0
- pinecall/gateway/api/desk.py +113 -0
- pinecall/gateway/api/entries.py +77 -0
- pinecall/gateway/api/evals.py +647 -0
- pinecall/gateway/api/fleet.py +73 -0
- pinecall/gateway/api/hosting.py +241 -0
- pinecall/gateway/api/judges.py +97 -0
- pinecall/gateway/api/keys.py +110 -0
- pinecall/gateway/api/line.py +142 -0
- pinecall/gateway/api/members.py +197 -0
- pinecall/gateway/api/metrics.py +226 -0
- pinecall/gateway/api/numbers.py +476 -0
- pinecall/gateway/api/ops.py +428 -0
- pinecall/gateway/api/org.py +283 -0
- pinecall/gateway/api/personas.py +157 -0
- pinecall/gateway/api/pipeline.py +206 -0
- pinecall/gateway/api/prompts.py +50 -0
- pinecall/gateway/api/providers.py +240 -0
- pinecall/gateway/api/recordings.py +89 -0
- pinecall/gateway/api/relay.py +169 -0
- pinecall/gateway/api/retrieval.py +403 -0
- pinecall/gateway/api/runner.py +109 -0
- pinecall/gateway/api/sessions.py +102 -0
- pinecall/gateway/api/settings.py +463 -0
- pinecall/gateway/api/signup.py +164 -0
- pinecall/gateway/api/sso_login.py +168 -0
- pinecall/gateway/api/threads.py +187 -0
- pinecall/gateway/api/usage.py +303 -0
- pinecall/gateway/api/visitors.py +222 -0
- pinecall/gateway/api/whatsapp.py +48 -0
- pinecall/gateway/api/widget.py +49 -0
- pinecall/gateway/app.py +504 -0
- pinecall/gateway/calls/__init__.py +0 -0
- pinecall/gateway/calls/binding.py +63 -0
- pinecall/gateway/calls/commands.py +18 -0
- pinecall/gateway/calls/inbox.py +100 -0
- pinecall/gateway/calls/known.py +23 -0
- pinecall/gateway/calls/owners.py +87 -0
- pinecall/gateway/calls/pump.py +33 -0
- pinecall/gateway/calls/serving.py +118 -0
- pinecall/gateway/calls/threads.py +367 -0
- pinecall/gateway/dispatching/__init__.py +0 -0
- pinecall/gateway/dispatching/arrivals.py +58 -0
- pinecall/gateway/dispatching/sweep.py +43 -0
- pinecall/gateway/ending/__init__.py +0 -0
- pinecall/gateway/ending/reaper.py +160 -0
- pinecall/gateway/ending/seal.py +312 -0
- pinecall/gateway/ending/stranded.py +117 -0
- pinecall/log/__init__.py +0 -0
- pinecall/log/_histogram.py +74 -0
- pinecall/log/_relay.py +259 -0
- pinecall/log/_writer.py +454 -0
- pinecall/log/days.py +154 -0
- pinecall/log/drift.py +550 -0
- pinecall/log/facts.py +358 -0
- pinecall/log/inbox.py +169 -0
- pinecall/log/lists.py +155 -0
- pinecall/log/logs.py +581 -0
- pinecall/log/openings.py +71 -0
- pinecall/log/private.py +135 -0
- pinecall/log/queries.py +229 -0
- pinecall/log/readers.py +207 -0
- pinecall/log/reduce.py +659 -0
- pinecall/log/refold.py +217 -0
- pinecall/log/store.py +370 -0
- pinecall/log/usage.py +242 -0
- pinecall/postgres/__init__.py +0 -0
- pinecall/postgres/migrate.py +202 -0
- pinecall/postgres/migrations/0001_schema.sql +591 -0
- pinecall/postgres/migrations/0002_worlds.sql +15 -0
- pinecall/postgres/migrations/0003_lent.sql +4 -0
- pinecall/postgres/migrations/0004_carriers.sql +23 -0
- pinecall/postgres/migrations/0005_retrieved_only.sql +11 -0
- pinecall/postgres/migrations/0006_persona_agents.sql +9 -0
- pinecall/postgres/migrations/0007_money_in_dollars.sql +27 -0
- pinecall/postgres/migrations/0008_lexicon_per_agent.sql +27 -0
- pinecall/postgres/migrations/0009_personas_per_agent.sql +31 -0
- pinecall/postgres/migrations/0010_agent_judges.sql +12 -0
- pinecall/postgres/migrations/0011_erasure.sql +32 -0
- pinecall/postgres/migrations/0012_org_policy.sql +10 -0
- pinecall/postgres/migrations/0013_calling_rules.sql +12 -0
- pinecall/postgres/migrations/0014_consents.sql +24 -0
- pinecall/postgres/migrations/0015_disclosure.sql +7 -0
- pinecall/postgres/migrations/0016_call_records.sql +21 -0
- pinecall/postgres/migrations/0017_reads.sql +17 -0
- pinecall/postgres/migrations/0018_hosting.sql +41 -0
- pinecall/postgres/migrations/0019_hosted_state.sql +10 -0
- pinecall/postgres/migrations/0020_written_once.sql +7 -0
- pinecall/postgres/migrations/0021_hosted_running.sql +21 -0
- pinecall/postgres/migrations/0022_sealed.sql +39 -0
- pinecall/postgres/migrations/0023_usage_totals.sql +158 -0
- pinecall/postgres/migrations/0024_log_key_by_day.sql +8 -0
- pinecall/postgres/migrations/0025_log_before_the_days.sql +15 -0
- pinecall/postgres/migrations/0026_log_before_the_days_validated.sql +4 -0
- pinecall/postgres/migrations/0027_log_by_day.sql +96 -0
- pinecall/postgres/migrations/0030_whatsapp_seen.sql +17 -0
- pinecall/postgres/migrations/0040_reads_widened.sql +15 -0
- pinecall/postgres/migrations/0060_drift.sql +62 -0
- pinecall/postgres/migrations/0061_canaries.sql +24 -0
- pinecall/postgres/migrations/0062_eval_cases.sql +23 -0
- pinecall/postgres/migrations/0063_prompts.sql +16 -0
- pinecall/postgres/migrations/0075_call_private.sql +14 -0
- pinecall/postgres/migrations/0076_recording_keys.sql +13 -0
- pinecall/postgres/migrations/0077_tokens_world.sql +7 -0
- pinecall/postgres/migrations/0078_facts_cost_by_stage.sql +12 -0
- pinecall/postgres/migrations/0079_judge_labels.sql +20 -0
- pinecall/postgres/migrations/0080_call_openings.sql +20 -0
- pinecall/postgres/migrations/0081_seal_lease.sql +7 -0
- pinecall/postgres/migrations/0082_caller_codes.sql +14 -0
- pinecall/postgres/migrations/0083_one_use_words.sql +15 -0
- pinecall/postgres/migrations/0084_knocks_and_run_leases.sql +23 -0
- pinecall/postgres/migrations/0085_seal_lease_holder.sql +8 -0
- pinecall/postgres/migrations/0086_route_origin.sql +17 -0
- pinecall/postgres/migrations/0087_carrier_networks.sql +20 -0
- pinecall/postgres/migrations/0088_route_last_call.sql +3 -0
- pinecall/postgres/migrations/0089_offers.sql +21 -0
- pinecall/postgres/migrations/0090_invitation_purpose.sql +5 -0
- pinecall/postgres/migrations/0091_head_opened_by.sql +6 -0
- pinecall/postgres/migrations/0092_key_parent.sql +6 -0
- pinecall/postgres/migrations/0093_code_tries.sql +10 -0
- pinecall/postgres/migrations/0094_route_approval.sql +12 -0
- pinecall/postgres/migrations/0095_sso_domain_proofs.sql +17 -0
- pinecall/postgres/migrations/0096_row_level_security.sql +38 -0
- pinecall/postgres/migrations/0097_case_status.sql +19 -0
- pinecall/postgres/pool.py +190 -0
- pinecall/process/__init__.py +0 -0
- pinecall/process/_objects.py +97 -0
- pinecall/process/box_settings.py +23 -0
- pinecall/process/connections.py +124 -0
- pinecall/process/metrics.py +127 -0
- pinecall/process/recordings.py +323 -0
- pinecall/process/resolver.py +41 -0
- pinecall/process/sealed_audio.py +173 -0
- pinecall/process/settings.py +534 -0
- pinecall/process/shared.py +158 -0
- pinecall/process/signal.py +416 -0
- pinecall/providers/__init__.py +0 -0
- pinecall/providers/build.py +570 -0
- pinecall/providers/catalog.py +266 -0
- pinecall/providers/credentials.py +230 -0
- pinecall/providers/declared.py +69 -0
- pinecall/providers/prices.py +240 -0
- pinecall/providers/tried.py +104 -0
- pinecall/providers/voices.py +174 -0
- pinecall/public/console/assets/index-BIfKPSgn.js +164 -0
- pinecall/public/console/assets/index-ClOTU-xX.css +1 -0
- pinecall/public/console/favicon.png +0 -0
- pinecall/public/console/index.html +20 -0
- pinecall/public/console/logo-mark.png +0 -0
- pinecall/public/console/pinecall-logo-dark.png +0 -0
- pinecall/public/console/pinecall-logo.png +0 -0
- pinecall/public/console/pinecall-mark.png +0 -0
- pinecall/public/console/sw.js +37 -0
- pinecall/public/widget/pinecall-widget.js +853 -0
- pinecall/py.typed +0 -0
- pinecall/retrieval/__init__.py +0 -0
- pinecall/retrieval/_search.py +186 -0
- pinecall/retrieval/_sections.py +70 -0
- pinecall/retrieval/embed.py +340 -0
- pinecall/retrieval/extraction.py +403 -0
- pinecall/retrieval/knowledge.py +659 -0
- pinecall/retrieval/lookups.py +192 -0
- pinecall/retrieval/memory.py +603 -0
- pinecall/runner/__init__.py +0 -0
- pinecall/runner/_kube.py +459 -0
- pinecall/runner/_plan.py +157 -0
- pinecall/runner/main.py +306 -0
- pinecall/session/__init__.py +0 -0
- pinecall/session/_agent.py +141 -0
- pinecall/session/_hearing.py +101 -0
- pinecall/session/_livekit.py +195 -0
- pinecall/session/_prompt.py +147 -0
- pinecall/session/_recording.py +237 -0
- pinecall/session/call.py +367 -0
- pinecall/session/clock.py +40 -0
- pinecall/session/hold.py +239 -0
- pinecall/session/room.py +626 -0
- pinecall/session/session.py +690 -0
- pinecall/session/text.py +144 -0
- pinecall/session/tools.py +483 -0
- pinecall/session/voice.py +118 -0
- pinecall/session/widget.py +201 -0
- pinecall/tenancy/__init__.py +0 -0
- pinecall/tenancy/admission.py +204 -0
- pinecall/tenancy/agents.py +164 -0
- pinecall/tenancy/canary.py +126 -0
- pinecall/tenancy/carrier_networks.py +156 -0
- pinecall/tenancy/carriers.py +265 -0
- pinecall/tenancy/codes.py +196 -0
- pinecall/tenancy/consents.py +167 -0
- pinecall/tenancy/dial_policy.py +405 -0
- pinecall/tenancy/disclosure.py +41 -0
- pinecall/tenancy/erasure.py +204 -0
- pinecall/tenancy/export.py +167 -0
- pinecall/tenancy/hosted_running.py +166 -0
- pinecall/tenancy/hosting.py +475 -0
- pinecall/tenancy/judges.py +126 -0
- pinecall/tenancy/keys.py +467 -0
- pinecall/tenancy/knocks.py +40 -0
- pinecall/tenancy/letters.py +378 -0
- pinecall/tenancy/mail.py +458 -0
- pinecall/tenancy/org_secrets.py +123 -0
- pinecall/tenancy/orgs.py +78 -0
- pinecall/tenancy/people.py +543 -0
- pinecall/tenancy/personas.py +145 -0
- pinecall/tenancy/policy.py +65 -0
- pinecall/tenancy/prompts.py +48 -0
- pinecall/tenancy/reads.py +73 -0
- pinecall/tenancy/recording_keys.py +41 -0
- pinecall/tenancy/remembered.py +148 -0
- pinecall/tenancy/retention.py +86 -0
- pinecall/tenancy/scopes.py +406 -0
- pinecall/tenancy/signin.py +622 -0
- pinecall/tenancy/spend.py +69 -0
- pinecall/tenancy/sso.py +431 -0
- pinecall/tenancy/sso_domains.py +132 -0
- pinecall/tenancy/throttle.py +88 -0
- pinecall/tenancy/tokens.py +400 -0
- pinecall/tenancy/traceback.py +70 -0
- pinecall/tenancy/usage.py +136 -0
- pinecall/tenancy/vault.py +204 -0
- pinecall/tenancy/words.py +144 -0
- pinecall/wire/__init__.py +0 -0
- pinecall/wire/commands.py +350 -0
- pinecall/wire/events.py +655 -0
- pinecall/wire/frames.py +65 -0
- pinecall/wire/metrics.py +287 -0
- pinecall/wire/parts.py +320 -0
- pinecall/wire/rest/__init__.py +0 -0
- pinecall/wire/rest/accounts.py +512 -0
- pinecall/wire/rest/agents.py +172 -0
- pinecall/wire/rest/calls.py +397 -0
- pinecall/wire/rest/evals.py +453 -0
- pinecall/wire/rest/fleet.py +69 -0
- pinecall/wire/rest/hosting.py +174 -0
- pinecall/wire/rest/numbers.py +280 -0
- pinecall/wire/rest/ops.py +342 -0
- pinecall/wire/rest/providers.py +83 -0
- pinecall/wire/rest/retrieval.py +301 -0
- pinecall/wire/rest/settings.py +184 -0
- pinecall/wire/rest/usage.py +245 -0
- pinecall/wire/room.py +61 -0
- pinecall/wire/scores.py +49 -0
- pinecall/wire/state.py +243 -0
- pinecall/worker/__init__.py +0 -0
- pinecall/worker/_job.py +655 -0
- pinecall/worker/_recorder.py +82 -0
- pinecall/worker/_traces.py +48 -0
- pinecall/worker/main.py +307 -0
- pinecall_runtime-0.1.6.dist-info/METADATA +212 -0
- pinecall_runtime-0.1.6.dist-info/RECORD +328 -0
- pinecall_runtime-0.1.6.dist-info/WHEEL +4 -0
- pinecall_runtime-0.1.6.dist-info/entry_points.txt +2 -0
- pinecall_runtime-0.1.6.dist-info/licenses/LICENSE +202 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""The calibration doors: a person labels what a judge should have said; each judge is judged."""
|
|
2
|
+
|
|
3
|
+
from typing import Annotated
|
|
4
|
+
|
|
5
|
+
from fastapi import APIRouter, Query
|
|
6
|
+
|
|
7
|
+
from pinecall.domain.errors import NotFound
|
|
8
|
+
from pinecall.evals import calibration
|
|
9
|
+
from pinecall.evals.calibration import Label, Where
|
|
10
|
+
from pinecall.gateway import _deps
|
|
11
|
+
from pinecall.gateway._deps import EvalsKey, GatewayDep, ScopeDep
|
|
12
|
+
from pinecall.log import queries
|
|
13
|
+
from pinecall.tenancy.keys import check_agent
|
|
14
|
+
from pinecall.wire.rest.evals import Calibration, JudgeAgreement, LabelRequest
|
|
15
|
+
|
|
16
|
+
router = APIRouter()
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
# The key must read the call, as a replay's does; the label is kept in the call's own world.
|
|
20
|
+
@router.post("/v1/evals/calibration", status_code=204)
|
|
21
|
+
async def label_call(
|
|
22
|
+
body: LabelRequest, key: EvalsKey, scope: ScopeDep, gateway: GatewayDep
|
|
23
|
+
) -> None:
|
|
24
|
+
"""Keep what one judge should have answered on a finished call, replacing the last label."""
|
|
25
|
+
await _deps.check_readable(gateway, _deps.Reader(acting=key, scope=scope), body.call)
|
|
26
|
+
kept = await queries.scope_of_call(gateway.connections.pool, body.call)
|
|
27
|
+
if kept is None or kept.scope is None:
|
|
28
|
+
raise NotFound(_deps.NO_SUCH_CALL.format(call=body.call))
|
|
29
|
+
check_agent(key.bearer, kept.agent)
|
|
30
|
+
where = Where(org=key.org, env=kept.scope.env, agent=kept.agent)
|
|
31
|
+
author = key.bearer.key.subject or key.bearer.key.key_id
|
|
32
|
+
label = Label(call=body.call, judge=body.judge, held=body.held, author=author, note=body.note)
|
|
33
|
+
await calibration.labelled(gateway.connections.pool, where, label)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@router.get("/v1/evals/calibration")
|
|
37
|
+
async def read_calibration(
|
|
38
|
+
key: EvalsKey, gateway: GatewayDep, agent: Annotated[str | None, Query()] = None
|
|
39
|
+
) -> Calibration:
|
|
40
|
+
"""Each judge's agreement with the labels on the key's world's calls, one agent's or all."""
|
|
41
|
+
if agent is not None:
|
|
42
|
+
check_agent(key.bearer, agent)
|
|
43
|
+
judged = await calibration.agreement(gateway.connections.pool, key.org, key.env, agent)
|
|
44
|
+
return Calibration(
|
|
45
|
+
judges=[
|
|
46
|
+
JudgeAgreement(
|
|
47
|
+
judge=item.judge,
|
|
48
|
+
labelled=item.labelled,
|
|
49
|
+
compared=item.compared,
|
|
50
|
+
agreed=item.agreed,
|
|
51
|
+
rate=item.rate,
|
|
52
|
+
trusted=item.trusted,
|
|
53
|
+
)
|
|
54
|
+
for item in judged
|
|
55
|
+
],
|
|
56
|
+
labels_to_judge=calibration.LABELS_TO_JUDGE,
|
|
57
|
+
agrees_at_least=calibration.AGREES_AT_LEAST,
|
|
58
|
+
)
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"""Callbacks: somebody the overflow told to wait, and the org's list of them."""
|
|
2
|
+
|
|
3
|
+
from typing import Annotated
|
|
4
|
+
|
|
5
|
+
from fastapi import APIRouter, Query
|
|
6
|
+
from pydantic import BaseModel
|
|
7
|
+
|
|
8
|
+
from pinecall.domain.errors import (
|
|
9
|
+
DeclarationRefused,
|
|
10
|
+
NotFound,
|
|
11
|
+
)
|
|
12
|
+
from pinecall.domain.person import THE_FLEET
|
|
13
|
+
from pinecall.gateway import _deps
|
|
14
|
+
from pinecall.gateway._deps import (
|
|
15
|
+
Acting,
|
|
16
|
+
CallsKey,
|
|
17
|
+
GatewayDep,
|
|
18
|
+
WorkerKey,
|
|
19
|
+
)
|
|
20
|
+
from pinecall.gateway._gateway import Gateway
|
|
21
|
+
from pinecall.log import queries
|
|
22
|
+
from pinecall.tenancy import keys
|
|
23
|
+
from pinecall.wire.events import CallbackRequested
|
|
24
|
+
from pinecall.wire.rest.calls import CallbackList, CallbackRequest, CallbackRow
|
|
25
|
+
|
|
26
|
+
router = APIRouter()
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
NOT_THIS_ORGS = "agent {agent} is not this org's"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
NAME_THE_CALL = "the fleet's key asks a call back for the call it serves: name the call"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
CALLBACK = "callback.requested"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
A_PAGE = 500
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class CallbackQuery(BaseModel):
|
|
42
|
+
"""Where the org's list of callbacks continues, and whose."""
|
|
43
|
+
|
|
44
|
+
after: int = 0
|
|
45
|
+
agent: str | None = None
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
# The overflow names the call it answered, and the agent must be that call's org's; an app
|
|
49
|
+
# names its own org's agent.
|
|
50
|
+
@router.post("/v1/callbacks", status_code=204)
|
|
51
|
+
async def request_callback(body: CallbackRequest, key: WorkerKey, gateway: GatewayDep) -> None:
|
|
52
|
+
"""Somebody the overflow told to wait for a call back, on the agent's log."""
|
|
53
|
+
keys.check_agent(key.bearer, body.agent)
|
|
54
|
+
owner = await gateway.logs.store.owner(body.agent)
|
|
55
|
+
fleet = THE_FLEET in key.bearer.key.scopes
|
|
56
|
+
acting_for = await _org_of_the_call(gateway, key, body.call) if fleet else key.org
|
|
57
|
+
if owner is None or owner != acting_for:
|
|
58
|
+
raise NotFound(NOT_THIS_ORGS.format(agent=body.agent))
|
|
59
|
+
wanted = CallbackRequested(
|
|
60
|
+
channel=body.channel, number=body.number, via="overflow", call=body.call, contact=None
|
|
61
|
+
)
|
|
62
|
+
await gateway.logs.agent(body.agent).append(CALLBACK, wanted.written())
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
@router.get("/v1/callbacks", response_model_exclude_unset=True)
|
|
66
|
+
async def list_callbacks(
|
|
67
|
+
key: CallsKey, gateway: GatewayDep, query: Annotated[CallbackQuery, Query()]
|
|
68
|
+
) -> CallbackList:
|
|
69
|
+
"""The org's callbacks in the key's world, oldest first, a page at a time."""
|
|
70
|
+
page = await gateway.logs.store.across([CALLBACK], after=query.after, limit=A_PAGE)
|
|
71
|
+
# An agent's log holds both worlds' callbacks: each is the world of the call it names.
|
|
72
|
+
named = [str(item.entry.data["call"]) for item in page if item.entry.data.get("call")]
|
|
73
|
+
worlds = await queries.envs_of_calls(gateway.connections.pool, named)
|
|
74
|
+
ours = [
|
|
75
|
+
item
|
|
76
|
+
for item in page
|
|
77
|
+
if item.org == key.org
|
|
78
|
+
and worlds.get(str(item.entry.data.get("call"))) == key.env
|
|
79
|
+
and (query.agent is None or item.entry.agent == query.agent)
|
|
80
|
+
]
|
|
81
|
+
return CallbackList(
|
|
82
|
+
requests=[
|
|
83
|
+
CallbackRow.model_validate(
|
|
84
|
+
{
|
|
85
|
+
"position": our.position,
|
|
86
|
+
"agent": our.entry.agent,
|
|
87
|
+
"ts": our.entry.ts,
|
|
88
|
+
**our.entry.data,
|
|
89
|
+
}
|
|
90
|
+
)
|
|
91
|
+
for our in ours
|
|
92
|
+
],
|
|
93
|
+
next=page[-1].position if len(page) == A_PAGE else None,
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
async def _org_of_the_call(gateway: Gateway, key: Acting, call: str | None) -> str:
|
|
98
|
+
if call is None:
|
|
99
|
+
raise DeclarationRefused(NAME_THE_CALL)
|
|
100
|
+
kept = await queries.scope_of_call(gateway.connections.pool, call)
|
|
101
|
+
if kept is None or kept.scope is None:
|
|
102
|
+
raise NotFound(_deps.NEVER_OPENED.format(call=call))
|
|
103
|
+
if kept.scope.env != key.env:
|
|
104
|
+
raise NotFound(_deps.NO_SUCH_CALL.format(call=call))
|
|
105
|
+
return kept.scope.org
|