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,245 @@
|
|
|
1
|
+
"""The bodies of the org's meters: the usage feed, a window's insights, its drift, the limits."""
|
|
2
|
+
|
|
3
|
+
from typing import Literal
|
|
4
|
+
|
|
5
|
+
from pinecall.domain.names import Env
|
|
6
|
+
from pinecall.wire.frames import WireModel
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class UsageTotals(WireModel):
|
|
10
|
+
"""What was consumed: calls, minutes, turns, tokens, characters, judge calls, the cost."""
|
|
11
|
+
|
|
12
|
+
calls: int
|
|
13
|
+
minutes: float
|
|
14
|
+
messages: int
|
|
15
|
+
input_tokens: int
|
|
16
|
+
output_tokens: int
|
|
17
|
+
characters: int
|
|
18
|
+
judge_calls: int
|
|
19
|
+
cost_usd: float
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
# Flat, as v1 wrote it: a billing layer that reads the feed today reads it unchanged at the cutover.
|
|
23
|
+
class UsageRow(WireModel):
|
|
24
|
+
"""One metered entry: whose it was, which call, what it consumed, and where the feed is."""
|
|
25
|
+
|
|
26
|
+
cursor: int
|
|
27
|
+
org: str
|
|
28
|
+
agent: str
|
|
29
|
+
call: str
|
|
30
|
+
type: str
|
|
31
|
+
at: float
|
|
32
|
+
minutes: float
|
|
33
|
+
messages: int
|
|
34
|
+
input_tokens: int
|
|
35
|
+
output_tokens: int
|
|
36
|
+
characters: int
|
|
37
|
+
judge_calls: int
|
|
38
|
+
cost_usd: float
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class UsagePage(WireModel):
|
|
42
|
+
"""GET /v1/usage: the org's metered rows after the cursor, their totals, the next cursor."""
|
|
43
|
+
|
|
44
|
+
rows: list[UsageRow]
|
|
45
|
+
totals: UsageTotals | None
|
|
46
|
+
next: int | None
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class BoxUsagePage(WireModel):
|
|
50
|
+
"""GET /v1/ops/usage: every org's metered rows after the cursor, totals per org, the next."""
|
|
51
|
+
|
|
52
|
+
rows: list[UsageRow]
|
|
53
|
+
totals: dict[str, UsageTotals]
|
|
54
|
+
next: int | None
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class InsightsConversations(WireModel):
|
|
58
|
+
"""How many calls started in the window, and in the window of the same length before it."""
|
|
59
|
+
|
|
60
|
+
now: int
|
|
61
|
+
before: int
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class InsightsChannels(WireModel):
|
|
65
|
+
"""The window's calls by the door they came in by."""
|
|
66
|
+
|
|
67
|
+
phone: int
|
|
68
|
+
web: int
|
|
69
|
+
whatsapp: int
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class InsightsSpend(WireModel):
|
|
73
|
+
"""What one agent's window cost by stage, in US dollars, and per minute of its ended calls."""
|
|
74
|
+
|
|
75
|
+
llm_usd: float
|
|
76
|
+
stt_usd: float
|
|
77
|
+
tts_usd: float
|
|
78
|
+
phone_usd: float
|
|
79
|
+
platform_usd: float
|
|
80
|
+
minutes: float
|
|
81
|
+
per_minute_usd: float | None
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class InsightsAgent(WireModel):
|
|
85
|
+
"""One agent's window: its calls, the share of judgments it held, what it cost by stage."""
|
|
86
|
+
|
|
87
|
+
slug: str
|
|
88
|
+
calls: int
|
|
89
|
+
score: float | None
|
|
90
|
+
spend: InsightsSpend
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class InsightsStage(WireModel):
|
|
94
|
+
"""One stage of the window's turns on one vendor and model: how slow, how sure the ears were."""
|
|
95
|
+
|
|
96
|
+
stage: Literal["stt", "llm", "tts"]
|
|
97
|
+
vendor: str | None
|
|
98
|
+
model: str | None
|
|
99
|
+
turns: int
|
|
100
|
+
median_s: float | None
|
|
101
|
+
p95_s: float | None
|
|
102
|
+
confidence: float | None
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
class InsightsBudget(WireModel):
|
|
106
|
+
"""What the org may spend in a month and what it has spent so far, both worlds together."""
|
|
107
|
+
|
|
108
|
+
limit_usd: int | None
|
|
109
|
+
spent_usd_month: float
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class InsightsEnding(WireModel):
|
|
113
|
+
"""One way the window's calls ended, and how many did."""
|
|
114
|
+
|
|
115
|
+
reason: str
|
|
116
|
+
count: int
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class InsightsDay(WireModel):
|
|
120
|
+
"""One UTC day of the window: its calls by door, what they cost, how their judges answered."""
|
|
121
|
+
|
|
122
|
+
day: str
|
|
123
|
+
phone: int
|
|
124
|
+
web: int
|
|
125
|
+
whatsapp: int
|
|
126
|
+
spend_usd: float
|
|
127
|
+
judged: int
|
|
128
|
+
passed: int
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
class Insights(WireModel):
|
|
132
|
+
"""GET /v1/insights: whole UTC days of the key's world and scope, counted off the call index."""
|
|
133
|
+
|
|
134
|
+
day: str
|
|
135
|
+
days: int
|
|
136
|
+
timezone: str
|
|
137
|
+
conversations: InsightsConversations
|
|
138
|
+
resolved_rate: float | None
|
|
139
|
+
median_e2e_s: float | None
|
|
140
|
+
spend_usd: float
|
|
141
|
+
channels: InsightsChannels
|
|
142
|
+
judged: int
|
|
143
|
+
passed: int
|
|
144
|
+
escalated: int
|
|
145
|
+
mean_length_s: float | None
|
|
146
|
+
endings: list[InsightsEnding]
|
|
147
|
+
series: list[InsightsDay]
|
|
148
|
+
sessions_total: int
|
|
149
|
+
live: int
|
|
150
|
+
agents: list[InsightsAgent]
|
|
151
|
+
stages: list[InsightsStage]
|
|
152
|
+
budget: InsightsBudget
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
class DriftSide(WireModel):
|
|
156
|
+
"""One side of a drift as asked: a day, a version; and the versions its calls ran."""
|
|
157
|
+
|
|
158
|
+
day: str | None
|
|
159
|
+
version: int | None
|
|
160
|
+
versions: list[int]
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
class JudgeTally(WireModel):
|
|
164
|
+
"""One judge on one side: its verdicts that held, those settled, and the share that held."""
|
|
165
|
+
|
|
166
|
+
held: int
|
|
167
|
+
judged: int
|
|
168
|
+
pass_rate: float | None
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
class DriftJudge(WireModel):
|
|
172
|
+
"""One judge on both sides, how far its pass rate moved, and whether its question changed."""
|
|
173
|
+
|
|
174
|
+
name: str
|
|
175
|
+
before: JudgeTally | None
|
|
176
|
+
after: JudgeTally | None
|
|
177
|
+
moved: float | None
|
|
178
|
+
criteria_changed: bool
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
class StageTally(WireModel):
|
|
182
|
+
"""One stage on one side: its turns, median and p95 in seconds, the ears' confidence."""
|
|
183
|
+
|
|
184
|
+
turns: int
|
|
185
|
+
median_s: float | None
|
|
186
|
+
p95_s: float | None
|
|
187
|
+
confidence: float | None
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
class DriftStage(WireModel):
|
|
191
|
+
"""One stage on one vendor and model on both sides, and how far its median and p95 moved."""
|
|
192
|
+
|
|
193
|
+
stage: Literal["stt", "llm", "tts"]
|
|
194
|
+
vendor: str | None
|
|
195
|
+
model: str | None
|
|
196
|
+
before: StageTally | None
|
|
197
|
+
after: StageTally | None
|
|
198
|
+
median_moved_s: float | None
|
|
199
|
+
p95_moved_s: float | None
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
class DriftVersion(WireModel):
|
|
203
|
+
"""A version of the agent's settings a side ran or that was set between: who, when, why."""
|
|
204
|
+
|
|
205
|
+
version: int
|
|
206
|
+
holder: str
|
|
207
|
+
author: str
|
|
208
|
+
note: str | None
|
|
209
|
+
set_at: float
|
|
210
|
+
ran_before: bool
|
|
211
|
+
ran_after: bool
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
class Drift(WireModel):
|
|
215
|
+
"""GET /v1/insights/drift: what moved between two days or versions of an agent, and why."""
|
|
216
|
+
|
|
217
|
+
agent: str
|
|
218
|
+
world: Env
|
|
219
|
+
before: DriftSide
|
|
220
|
+
after: DriftSide
|
|
221
|
+
judges: list[DriftJudge]
|
|
222
|
+
stages: list[DriftStage]
|
|
223
|
+
versions: list[DriftVersion]
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
class Limit(WireModel):
|
|
227
|
+
"""One quota: the limit the org was given, and how much of it is used."""
|
|
228
|
+
|
|
229
|
+
limit: int | None
|
|
230
|
+
used: float
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
class Limits(WireModel):
|
|
234
|
+
"""GET /v1/limits: what the key's org may use in the world and has used, and its lends."""
|
|
235
|
+
|
|
236
|
+
minutes: Limit
|
|
237
|
+
messages: Limit
|
|
238
|
+
llm_tokens: Limit
|
|
239
|
+
concurrent_calls: Limit
|
|
240
|
+
agents: Limit
|
|
241
|
+
seats: Limit
|
|
242
|
+
numbers: Limit
|
|
243
|
+
lends: list[str] | None
|
|
244
|
+
billing_url: str | None
|
|
245
|
+
world: Env
|
pinecall/wire/room.py
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""The room's events: the room opened, who joined, left and spoke, what they published, sent."""
|
|
2
|
+
|
|
3
|
+
from pinecall.domain.names import Channel, JsonObject
|
|
4
|
+
from pinecall.wire.frames import WireModel
|
|
5
|
+
from pinecall.wire.parts import ParticipantKind, TrackKind, TrackSource
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class RoomOpened(WireModel):
|
|
9
|
+
"""The LiveKit room exists and the call lives in it; a text session never logs this."""
|
|
10
|
+
|
|
11
|
+
name: str
|
|
12
|
+
sid: str
|
|
13
|
+
channel: Channel
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
# The attributes travel verbatim: the caller's number is a fact of the room, not a field of ours.
|
|
17
|
+
class ParticipantJoined(WireModel):
|
|
18
|
+
"""Somebody joined the room."""
|
|
19
|
+
|
|
20
|
+
identity: str
|
|
21
|
+
kind: ParticipantKind
|
|
22
|
+
name: str | None = None
|
|
23
|
+
attributes: JsonObject
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class ParticipantLeft(WireModel):
|
|
27
|
+
"""Somebody left the room; when it is the caller, call.ended follows."""
|
|
28
|
+
|
|
29
|
+
identity: str
|
|
30
|
+
reason: str
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class ParticipantSpeaking(WireModel):
|
|
34
|
+
"""The room's own voice activity for one participant flipped; a light for the console."""
|
|
35
|
+
|
|
36
|
+
identity: str
|
|
37
|
+
speaking: bool
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class TrackPublished(WireModel):
|
|
41
|
+
"""A participant put a track on the room: their microphone, their camera, a screen."""
|
|
42
|
+
|
|
43
|
+
identity: str
|
|
44
|
+
kind: TrackKind
|
|
45
|
+
source: TrackSource
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class TrackUnpublished(WireModel):
|
|
49
|
+
"""A participant's track left the room."""
|
|
50
|
+
|
|
51
|
+
identity: str
|
|
52
|
+
kind: TrackKind
|
|
53
|
+
source: TrackSource
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class RoomSent(WireModel):
|
|
57
|
+
"""The agent pushed a payload to a browser in the room; the payload stays out of the log."""
|
|
58
|
+
|
|
59
|
+
topic: str
|
|
60
|
+
to: str | None = None
|
|
61
|
+
bytes: int
|
pinecall/wire/scores.py
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"""What the judges said about a call: call.score, one judgment per judge, and its evidence."""
|
|
2
|
+
|
|
3
|
+
from pydantic import AliasChoices, Field
|
|
4
|
+
|
|
5
|
+
from pinecall.wire.frames import WireModel
|
|
6
|
+
from pinecall.wire.parts import ScoreVerdict
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class JudgmentEvidence(WireModel):
|
|
10
|
+
"""Where in the call's own log a judgment is about."""
|
|
11
|
+
|
|
12
|
+
seqs: list[int]
|
|
13
|
+
said: str | None = None
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class Judgment(WireModel):
|
|
17
|
+
"""One judge's answer about one call."""
|
|
18
|
+
|
|
19
|
+
name: str
|
|
20
|
+
verdict: ScoreVerdict
|
|
21
|
+
criteria: str
|
|
22
|
+
reason: str
|
|
23
|
+
evidence: JudgmentEvidence
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class JudgedBy(WireModel):
|
|
27
|
+
"""Who gave a score: the judge model, and one hash of every question the panel asked."""
|
|
28
|
+
|
|
29
|
+
# None: the panel was settled by code alone, no model asked.
|
|
30
|
+
provider: str | None
|
|
31
|
+
model: str | None
|
|
32
|
+
criteria: str
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class CallScore(WireModel):
|
|
36
|
+
"""The last entry of a call: what the judges said about it at hang-up, one row per judge."""
|
|
37
|
+
|
|
38
|
+
passed: bool | None = None
|
|
39
|
+
not_judged: str | None = None
|
|
40
|
+
judges: list[Judgment]
|
|
41
|
+
panel: list[str] | None = None
|
|
42
|
+
judge_calls: int
|
|
43
|
+
# A score written before money in dollars said it in euros: the same number, read as dollars.
|
|
44
|
+
judge_cost_usd: float | None = Field(
|
|
45
|
+
default=None, validation_alias=AliasChoices("judge_cost_usd", "judge_cost_eur")
|
|
46
|
+
)
|
|
47
|
+
# Absent on a score written before 10.6, or with nothing judged: drift tells a worse agent from
|
|
48
|
+
# a changed judge by it.
|
|
49
|
+
judged_by: JudgedBy | None = None
|
pinecall/wire/state.py
ADDED
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
"""What a log reduces to: State and its parts."""
|
|
2
|
+
|
|
3
|
+
from typing import Annotated, Literal
|
|
4
|
+
|
|
5
|
+
from pydantic import Field
|
|
6
|
+
|
|
7
|
+
from pinecall.domain.agent import EventSource
|
|
8
|
+
from pinecall.domain.names import Channel, Direction, Json, JsonObject
|
|
9
|
+
from pinecall.wire.frames import WireModel
|
|
10
|
+
from pinecall.wire.metrics import (
|
|
11
|
+
AgentTurnMetrics,
|
|
12
|
+
AvatarMetrics,
|
|
13
|
+
EOTInferenceMetrics,
|
|
14
|
+
EOUMetrics,
|
|
15
|
+
InterruptionMetrics,
|
|
16
|
+
LLMMetrics,
|
|
17
|
+
ModelUsage,
|
|
18
|
+
RealtimeModelMetrics,
|
|
19
|
+
STTMetrics,
|
|
20
|
+
TTSMetrics,
|
|
21
|
+
UserTurnMetrics,
|
|
22
|
+
VADMetrics,
|
|
23
|
+
)
|
|
24
|
+
from pinecall.wire.parts import (
|
|
25
|
+
AgentState,
|
|
26
|
+
CallStatus,
|
|
27
|
+
Contact,
|
|
28
|
+
Cost,
|
|
29
|
+
DocSource,
|
|
30
|
+
EndReason,
|
|
31
|
+
MemoryOp,
|
|
32
|
+
ParticipantKind,
|
|
33
|
+
Route,
|
|
34
|
+
Supervisor,
|
|
35
|
+
TransferMode,
|
|
36
|
+
UserState,
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class UserTurn(WireModel):
|
|
41
|
+
"""One finished turn of the caller, with what the session measured about it."""
|
|
42
|
+
|
|
43
|
+
role: Literal["user"] = "user"
|
|
44
|
+
speech_id: str
|
|
45
|
+
item_id: str | None = None
|
|
46
|
+
text: str
|
|
47
|
+
language: str | None = None
|
|
48
|
+
transcript_confidence: float | None = None
|
|
49
|
+
metrics: UserTurnMetrics
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class AgentTurn(WireModel):
|
|
53
|
+
"""One finished reply of the agent, with what the session measured about it."""
|
|
54
|
+
|
|
55
|
+
role: Literal["agent"] = "agent"
|
|
56
|
+
speech_id: str
|
|
57
|
+
item_id: str | None = None
|
|
58
|
+
text: str
|
|
59
|
+
interrupted: bool
|
|
60
|
+
metrics: AgentTurnMetrics
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
type Turn = Annotated[UserTurn | AgentTurn, Field(discriminator="role")]
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class CollectedMetrics(WireModel):
|
|
67
|
+
"""Every raw metric block of the call, by kind, in the order it arrived."""
|
|
68
|
+
|
|
69
|
+
llm: list[LLMMetrics]
|
|
70
|
+
stt: list[STTMetrics]
|
|
71
|
+
tts: list[TTSMetrics]
|
|
72
|
+
vad: list[VADMetrics]
|
|
73
|
+
eou: list[EOUMetrics]
|
|
74
|
+
eot: list[EOTInferenceMetrics]
|
|
75
|
+
interruption: list[InterruptionMetrics]
|
|
76
|
+
realtime: list[RealtimeModelMetrics]
|
|
77
|
+
avatar: list[AvatarMetrics]
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class ToolRun(WireModel):
|
|
81
|
+
"""One tool call and, once the app answered, its result."""
|
|
82
|
+
|
|
83
|
+
call_id: str
|
|
84
|
+
name: str
|
|
85
|
+
arguments: JsonObject
|
|
86
|
+
speech_id: str | None = None
|
|
87
|
+
status: Literal["running", "done", "failed"]
|
|
88
|
+
output: Json = None
|
|
89
|
+
error: str | None = None
|
|
90
|
+
summary: str | None = None
|
|
91
|
+
duration_s: float | None = None
|
|
92
|
+
seq: int
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class PromptBlockState(WireModel):
|
|
96
|
+
"""What is known about one block of the prompt without storing its text."""
|
|
97
|
+
|
|
98
|
+
hash: str
|
|
99
|
+
chars: int
|
|
100
|
+
seq: int
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
type PromptState = dict[str, PromptBlockState]
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
class Confirm(WireModel):
|
|
107
|
+
"""One confirmation the platform asked for, and how it went."""
|
|
108
|
+
|
|
109
|
+
tool: str
|
|
110
|
+
call_id: str
|
|
111
|
+
audience: str
|
|
112
|
+
phrase: str
|
|
113
|
+
status: Literal["pending", "granted", "declined"]
|
|
114
|
+
said: str | None = None
|
|
115
|
+
reason: str | None = None
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
class Handoff(WireModel):
|
|
119
|
+
"""Whether a supervisor holds the line right now."""
|
|
120
|
+
|
|
121
|
+
active: bool
|
|
122
|
+
by: Supervisor | None
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
class TransferState(WireModel):
|
|
126
|
+
"""The transfer in flight or the one that happened."""
|
|
127
|
+
|
|
128
|
+
to: str
|
|
129
|
+
mode: TransferMode | None = None
|
|
130
|
+
status: Literal["requested", "done", "failed"]
|
|
131
|
+
by: Literal["agent", "supervisor"]
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
class AttentionState(WireModel):
|
|
135
|
+
"""The agent's last ask for a person, until attention.answered settles it."""
|
|
136
|
+
|
|
137
|
+
reason: str
|
|
138
|
+
wait_s: float
|
|
139
|
+
status: Literal["open", "answered", "lapsed"]
|
|
140
|
+
asked_at: float
|
|
141
|
+
by: Supervisor | None
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
class LiveTranscript(WireModel):
|
|
145
|
+
"""The words on screen right now: interim transcripts that a finished turn clears."""
|
|
146
|
+
|
|
147
|
+
user: str | None
|
|
148
|
+
agent: str | None
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
class Gap(WireModel):
|
|
152
|
+
"""A stretch of seqs this reader never saw."""
|
|
153
|
+
|
|
154
|
+
from_seq: int
|
|
155
|
+
to_seq: int
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
class LoggedError(WireModel):
|
|
159
|
+
"""An error entry, kept so the console can show what went wrong and when."""
|
|
160
|
+
|
|
161
|
+
seq: int
|
|
162
|
+
code: str
|
|
163
|
+
message: str
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
class Participant(WireModel):
|
|
167
|
+
"""One participant in the room right now, as the room reported them when they joined."""
|
|
168
|
+
|
|
169
|
+
identity: str
|
|
170
|
+
kind: ParticipantKind
|
|
171
|
+
name: str | None = None
|
|
172
|
+
joined_at: float
|
|
173
|
+
speaking: bool
|
|
174
|
+
attributes: JsonObject
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
class Room(WireModel):
|
|
178
|
+
"""The LiveKit room the call lives in, and who is in it right now."""
|
|
179
|
+
|
|
180
|
+
name: str
|
|
181
|
+
sid: str
|
|
182
|
+
participants: list[Participant]
|
|
183
|
+
caller: str | None
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
class ReceivedEvent(WireModel):
|
|
187
|
+
"""One fact that reached the agent from outside, kept by name and origin; its data is at seq."""
|
|
188
|
+
|
|
189
|
+
seq: int
|
|
190
|
+
name: str
|
|
191
|
+
source: EventSource
|
|
192
|
+
identity: str | None = None
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
class CustomNote(WireModel):
|
|
196
|
+
"""A line the app wrote into the log with call.log."""
|
|
197
|
+
|
|
198
|
+
seq: int
|
|
199
|
+
name: str
|
|
200
|
+
data: JsonObject
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
class State(WireModel):
|
|
204
|
+
"""The whole of what a log says, at the seq it was read to."""
|
|
205
|
+
|
|
206
|
+
seq: int
|
|
207
|
+
agent: str
|
|
208
|
+
call: str | None
|
|
209
|
+
status: CallStatus
|
|
210
|
+
channel: Channel | None
|
|
211
|
+
direction: Direction | None
|
|
212
|
+
from_: str | None = Field(alias="from")
|
|
213
|
+
to: str | None
|
|
214
|
+
caller: Contact | None
|
|
215
|
+
room: Room | None
|
|
216
|
+
started_at: float | None
|
|
217
|
+
ended_at: float | None
|
|
218
|
+
end_reason: EndReason | None
|
|
219
|
+
outcome: str | None
|
|
220
|
+
user_state: UserState | None
|
|
221
|
+
agent_state: AgentState | None
|
|
222
|
+
live: LiveTranscript
|
|
223
|
+
turns: list[Turn]
|
|
224
|
+
metrics: CollectedMetrics
|
|
225
|
+
tools: list[ToolRun]
|
|
226
|
+
app_state: JsonObject
|
|
227
|
+
events: list[ReceivedEvent]
|
|
228
|
+
prompt: PromptState
|
|
229
|
+
tools_visible: list[str]
|
|
230
|
+
confirms: list[Confirm]
|
|
231
|
+
memory: list[MemoryOp]
|
|
232
|
+
sources: list[DocSource]
|
|
233
|
+
handoff: Handoff
|
|
234
|
+
held: bool
|
|
235
|
+
muted: bool
|
|
236
|
+
transfer: TransferState | None
|
|
237
|
+
attention: AttentionState | None = None
|
|
238
|
+
usage: list[ModelUsage]
|
|
239
|
+
cost: Cost | None
|
|
240
|
+
routes: list[Route]
|
|
241
|
+
gaps: list[Gap]
|
|
242
|
+
errors: list[LoggedError]
|
|
243
|
+
custom: list[CustomNote]
|
|
File without changes
|