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
pinecall/wire/metrics.py
ADDED
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
"""Every livekit-agents 1.8 metric and usage row, verbatim."""
|
|
2
|
+
|
|
3
|
+
from typing import Annotated, Literal
|
|
4
|
+
|
|
5
|
+
from pydantic import Field
|
|
6
|
+
|
|
7
|
+
from pinecall.wire.frames import WireModel
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Metadata(WireModel):
|
|
11
|
+
"""Which model and provider produced a block."""
|
|
12
|
+
|
|
13
|
+
model_name: str | None = None
|
|
14
|
+
model_provider: str | None = None
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class LLMMetrics(WireModel):
|
|
18
|
+
"""One LLM request, measured by the session's llm node."""
|
|
19
|
+
|
|
20
|
+
type: Literal["llm_metrics"] = "llm_metrics"
|
|
21
|
+
label: str
|
|
22
|
+
request_id: str
|
|
23
|
+
timestamp: float
|
|
24
|
+
duration: float
|
|
25
|
+
ttft: float
|
|
26
|
+
cancelled: bool
|
|
27
|
+
completion_tokens: int
|
|
28
|
+
prompt_tokens: int
|
|
29
|
+
prompt_cached_tokens: int
|
|
30
|
+
cache_creation_tokens: int | None = None
|
|
31
|
+
reasoning_tokens: int | None = None
|
|
32
|
+
total_tokens: int
|
|
33
|
+
tokens_per_second: float
|
|
34
|
+
speech_id: str | None = None
|
|
35
|
+
metadata: Metadata | None = None
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class STTMetrics(WireModel):
|
|
39
|
+
"""One speech-to-text request, measured by the session's stt node."""
|
|
40
|
+
|
|
41
|
+
type: Literal["stt_metrics"] = "stt_metrics"
|
|
42
|
+
label: str
|
|
43
|
+
request_id: str
|
|
44
|
+
timestamp: float
|
|
45
|
+
duration: float
|
|
46
|
+
audio_duration: float
|
|
47
|
+
input_tokens: int | None = None
|
|
48
|
+
output_tokens: int | None = None
|
|
49
|
+
streamed: bool
|
|
50
|
+
acquire_time: float | None = None
|
|
51
|
+
connection_reused: bool | None = None
|
|
52
|
+
metadata: Metadata | None = None
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class TTSMetrics(WireModel):
|
|
56
|
+
"""One text-to-speech request, measured by the session's tts node."""
|
|
57
|
+
|
|
58
|
+
type: Literal["tts_metrics"] = "tts_metrics"
|
|
59
|
+
label: str
|
|
60
|
+
request_id: str
|
|
61
|
+
timestamp: float
|
|
62
|
+
ttfb: float
|
|
63
|
+
duration: float
|
|
64
|
+
audio_duration: float
|
|
65
|
+
cancelled: bool
|
|
66
|
+
characters_count: int
|
|
67
|
+
input_tokens: int | None = None
|
|
68
|
+
output_tokens: int | None = None
|
|
69
|
+
streamed: bool
|
|
70
|
+
acquire_time: float | None = None
|
|
71
|
+
connection_reused: bool | None = None
|
|
72
|
+
segment_id: str | None = None
|
|
73
|
+
speech_id: str | None = None
|
|
74
|
+
metadata: Metadata | None = None
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class VADMetrics(WireModel):
|
|
78
|
+
"""The voice activity detector's health, reported about once a second while it runs."""
|
|
79
|
+
|
|
80
|
+
type: Literal["vad_metrics"] = "vad_metrics"
|
|
81
|
+
label: str
|
|
82
|
+
timestamp: float
|
|
83
|
+
idle_time: float
|
|
84
|
+
inference_duration_total: float
|
|
85
|
+
inference_count: int
|
|
86
|
+
metadata: Metadata | None = None
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class EOUMetrics(WireModel):
|
|
90
|
+
"""How long the session took to decide that the caller had finished."""
|
|
91
|
+
|
|
92
|
+
type: Literal["eou_metrics"] = "eou_metrics"
|
|
93
|
+
timestamp: float
|
|
94
|
+
end_of_utterance_delay: float
|
|
95
|
+
transcription_delay: float
|
|
96
|
+
on_user_turn_completed_delay: float
|
|
97
|
+
speech_id: str | None = None
|
|
98
|
+
metadata: Metadata | None = None
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
class EOTInferenceMetrics(WireModel):
|
|
102
|
+
"""One prediction by the end-of-turn model."""
|
|
103
|
+
|
|
104
|
+
type: Literal["eot_inference_metrics"] = "eot_inference_metrics"
|
|
105
|
+
timestamp: float
|
|
106
|
+
total_duration: float
|
|
107
|
+
detection_delay: float
|
|
108
|
+
prediction_duration: float
|
|
109
|
+
num_requests: int | None = None
|
|
110
|
+
metadata: Metadata | None = None
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
class InterruptionMetrics(WireModel):
|
|
114
|
+
"""The interruption detector's latest inference and its running counts."""
|
|
115
|
+
|
|
116
|
+
type: Literal["interruption_metrics"] = "interruption_metrics"
|
|
117
|
+
timestamp: float
|
|
118
|
+
total_duration: float
|
|
119
|
+
prediction_duration: float
|
|
120
|
+
detection_delay: float
|
|
121
|
+
num_interruptions: int
|
|
122
|
+
num_backchannels: int
|
|
123
|
+
num_requests: int
|
|
124
|
+
metadata: Metadata | None = None
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
class RealtimeCachedTokenDetails(WireModel):
|
|
128
|
+
"""Of a realtime model's cached input, how much was audio, text or image."""
|
|
129
|
+
|
|
130
|
+
audio_tokens: int | None = None
|
|
131
|
+
text_tokens: int | None = None
|
|
132
|
+
image_tokens: int | None = None
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
class RealtimeInputTokenDetails(WireModel):
|
|
136
|
+
"""What a realtime model read, by kind, with the cached part broken out."""
|
|
137
|
+
|
|
138
|
+
audio_tokens: int | None = None
|
|
139
|
+
text_tokens: int | None = None
|
|
140
|
+
image_tokens: int | None = None
|
|
141
|
+
cached_tokens: int | None = None
|
|
142
|
+
cached_tokens_details: RealtimeCachedTokenDetails | None = None
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
class RealtimeOutputTokenDetails(WireModel):
|
|
146
|
+
"""What a realtime model produced, by kind."""
|
|
147
|
+
|
|
148
|
+
text_tokens: int | None = None
|
|
149
|
+
audio_tokens: int | None = None
|
|
150
|
+
image_tokens: int | None = None
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
class RealtimeModelMetrics(WireModel):
|
|
154
|
+
"""One response from a speech-to-speech model, which replaces STT, LLM and TTS at once."""
|
|
155
|
+
|
|
156
|
+
type: Literal["realtime_model_metrics"] = "realtime_model_metrics"
|
|
157
|
+
label: str | None = None
|
|
158
|
+
request_id: str
|
|
159
|
+
timestamp: float
|
|
160
|
+
duration: float | None = None
|
|
161
|
+
session_duration: float | None = None
|
|
162
|
+
ttft: float | None = None
|
|
163
|
+
cancelled: bool | None = None
|
|
164
|
+
input_tokens: int | None = None
|
|
165
|
+
output_tokens: int | None = None
|
|
166
|
+
total_tokens: int | None = None
|
|
167
|
+
tokens_per_second: float | None = None
|
|
168
|
+
input_token_details: RealtimeInputTokenDetails
|
|
169
|
+
output_token_details: RealtimeOutputTokenDetails
|
|
170
|
+
acquire_time: float | None = None
|
|
171
|
+
connection_reused: bool | None = None
|
|
172
|
+
metadata: Metadata | None = None
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
class AvatarMetrics(WireModel):
|
|
176
|
+
"""Timing of a video avatar worker, when one is in the chain."""
|
|
177
|
+
|
|
178
|
+
type: Literal["avatar_metrics"] = "avatar_metrics"
|
|
179
|
+
timestamp: float
|
|
180
|
+
playback_latency: float | None = None
|
|
181
|
+
session_started_time: float | None = None
|
|
182
|
+
avatar_joined_time: float | None = None
|
|
183
|
+
metadata: Metadata | None = None
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
class TurnMetadata(WireModel):
|
|
187
|
+
"""Which model handled one leg of a turn."""
|
|
188
|
+
|
|
189
|
+
model_name: str | None = None
|
|
190
|
+
model_provider: str | None = None
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
# Every field is optional: a text session has no speech to time.
|
|
194
|
+
class UserTurnMetrics(WireModel):
|
|
195
|
+
"""What the session measured about the caller's turn."""
|
|
196
|
+
|
|
197
|
+
started_speaking_at: float | None = None
|
|
198
|
+
stopped_speaking_at: float | None = None
|
|
199
|
+
transcription_delay: float | None = None
|
|
200
|
+
end_of_turn_delay: float | None = None
|
|
201
|
+
on_user_turn_completed_delay: float | None = None
|
|
202
|
+
stt_metadata: TurnMetadata | None = None
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
class AgentTurnMetrics(WireModel):
|
|
206
|
+
"""What the session measured about the agent's reply."""
|
|
207
|
+
|
|
208
|
+
started_speaking_at: float | None = None
|
|
209
|
+
stopped_speaking_at: float | None = None
|
|
210
|
+
llm_node_ttft: float | None = None
|
|
211
|
+
llm_node_tps: float | None = None
|
|
212
|
+
llm_node_ttfs: float | None = None
|
|
213
|
+
tts_node_ttfb: float | None = None
|
|
214
|
+
playback_latency: float | None = None
|
|
215
|
+
e2e_latency: float | None = None
|
|
216
|
+
provider_request_ids: list[str] | None = None
|
|
217
|
+
llm_metadata: TurnMetadata | None = None
|
|
218
|
+
tts_metadata: TurnMetadata | None = None
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
class LLMModelUsage(WireModel):
|
|
222
|
+
"""Everything one LLM consumed over the call."""
|
|
223
|
+
|
|
224
|
+
type: Literal["llm_usage"] = "llm_usage"
|
|
225
|
+
provider: str
|
|
226
|
+
model: str
|
|
227
|
+
input_tokens: int | None = None
|
|
228
|
+
input_cached_tokens: int | None = None
|
|
229
|
+
input_cache_creation_tokens: int | None = None
|
|
230
|
+
input_audio_tokens: int | None = None
|
|
231
|
+
input_cached_audio_tokens: int | None = None
|
|
232
|
+
input_text_tokens: int | None = None
|
|
233
|
+
input_cached_text_tokens: int | None = None
|
|
234
|
+
input_image_tokens: int | None = None
|
|
235
|
+
input_cached_image_tokens: int | None = None
|
|
236
|
+
output_tokens: int | None = None
|
|
237
|
+
output_audio_tokens: int | None = None
|
|
238
|
+
output_text_tokens: int | None = None
|
|
239
|
+
output_reasoning_tokens: int | None = None
|
|
240
|
+
session_duration: float | None = None
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
class TTSModelUsage(WireModel):
|
|
244
|
+
"""Everything one TTS consumed over the call."""
|
|
245
|
+
|
|
246
|
+
type: Literal["tts_usage"] = "tts_usage"
|
|
247
|
+
provider: str
|
|
248
|
+
model: str
|
|
249
|
+
input_tokens: int | None = None
|
|
250
|
+
output_tokens: int | None = None
|
|
251
|
+
characters_count: int | None = None
|
|
252
|
+
audio_duration: float | None = None
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
class STTModelUsage(WireModel):
|
|
256
|
+
"""Everything one STT consumed over the call."""
|
|
257
|
+
|
|
258
|
+
type: Literal["stt_usage"] = "stt_usage"
|
|
259
|
+
provider: str
|
|
260
|
+
model: str
|
|
261
|
+
input_tokens: int | None = None
|
|
262
|
+
output_tokens: int | None = None
|
|
263
|
+
audio_duration: float | None = None
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
class InterruptionModelUsage(WireModel):
|
|
267
|
+
"""How often the interruption detector was asked over the call."""
|
|
268
|
+
|
|
269
|
+
type: Literal["interruption_usage"] = "interruption_usage"
|
|
270
|
+
provider: str
|
|
271
|
+
model: str
|
|
272
|
+
total_requests: int | None = None
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
class EOTModelUsage(WireModel):
|
|
276
|
+
"""How often the end-of-turn model was asked over the call."""
|
|
277
|
+
|
|
278
|
+
type: Literal["eot_usage"] = "eot_usage"
|
|
279
|
+
provider: str
|
|
280
|
+
model: str
|
|
281
|
+
total_requests: int | None = None
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
type ModelUsage = Annotated[
|
|
285
|
+
LLMModelUsage | TTSModelUsage | STTModelUsage | InterruptionModelUsage | EOTModelUsage,
|
|
286
|
+
Field(discriminator="type"),
|
|
287
|
+
]
|
pinecall/wire/parts.py
ADDED
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
"""The parts events, commands and state share: the wire's words and its common shapes."""
|
|
2
|
+
|
|
3
|
+
from typing import Literal
|
|
4
|
+
|
|
5
|
+
from pydantic import AliasChoices, Field
|
|
6
|
+
|
|
7
|
+
from pinecall.domain.agent import EventSource
|
|
8
|
+
from pinecall.domain.names import Channel, Json, JsonObject
|
|
9
|
+
from pinecall.wire.frames import WireModel
|
|
10
|
+
|
|
11
|
+
# What a console may ask of the process standing in the agent's directory, relayed by the gateway.
|
|
12
|
+
type DevVerb = Literal[
|
|
13
|
+
"chat.roster",
|
|
14
|
+
"chat.start",
|
|
15
|
+
"chat.say",
|
|
16
|
+
"chat.end",
|
|
17
|
+
"view.render",
|
|
18
|
+
"simulate.start",
|
|
19
|
+
"goldens.roster",
|
|
20
|
+
"goldens.run",
|
|
21
|
+
"knowledge.roster",
|
|
22
|
+
"knowledge.push",
|
|
23
|
+
"knowledge.eval",
|
|
24
|
+
"memory.roster",
|
|
25
|
+
"memory.eval",
|
|
26
|
+
"memory.extraction",
|
|
27
|
+
"promote.roster",
|
|
28
|
+
"promote.write",
|
|
29
|
+
"drift.read",
|
|
30
|
+
"reproductions.roster",
|
|
31
|
+
"reproductions.read",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
# drained: the worker went down with the call on it; app_detached: the app closed mid-call.
|
|
35
|
+
type EndReason = Literal[
|
|
36
|
+
"caller_hung_up",
|
|
37
|
+
"agent_hung_up",
|
|
38
|
+
"supervisor_ended",
|
|
39
|
+
"transferred",
|
|
40
|
+
"no_answer",
|
|
41
|
+
"busy",
|
|
42
|
+
"dial_failed",
|
|
43
|
+
"timeout",
|
|
44
|
+
"drained",
|
|
45
|
+
"app_detached",
|
|
46
|
+
"error",
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
# platform covers timeouts, errors and a drained worker.
|
|
50
|
+
type EndedBy = Literal["caller", "agent", "supervisor", "platform"]
|
|
51
|
+
|
|
52
|
+
# skipped: no model was reachable inside the call's judging budget.
|
|
53
|
+
type ScoreVerdict = Literal["held", "broken", "deferred", "skipped"]
|
|
54
|
+
|
|
55
|
+
# cold: a REFER on the caller's SIP leg. warm: the number is dialled into the room.
|
|
56
|
+
type TransferMode = Literal["cold", "warm"]
|
|
57
|
+
|
|
58
|
+
type PromptRegion = Literal["static", "dynamic"]
|
|
59
|
+
type DocsMode = Literal["retrieved", "tool"]
|
|
60
|
+
type PlatformTool = Literal["recall", "search"]
|
|
61
|
+
type UserState = Literal["listening", "speaking", "away"]
|
|
62
|
+
type AgentState = Literal["initializing", "idle", "listening", "thinking", "speaking"]
|
|
63
|
+
type ParticipantKind = Literal["caller", "agent", "supervisor", "listener", "sip"]
|
|
64
|
+
type TrackKind = Literal["audio", "video", "screen"]
|
|
65
|
+
type TrackSource = Literal["microphone", "camera", "screen_share", "screen_share_audio", "unknown"]
|
|
66
|
+
type Visibility = Literal["public", "tenant", "pii"]
|
|
67
|
+
|
|
68
|
+
# Which projection a sink applies before a state or an entry leaves the platform.
|
|
69
|
+
type Projection = Literal["public", "tenant"]
|
|
70
|
+
|
|
71
|
+
type CallStatus = Literal["idle", "ringing", "dialing", "active", "ended"]
|
|
72
|
+
type SessionFlag = Literal["escalated", "low_score", "promise"]
|
|
73
|
+
type ThreadKind = Literal["in", "out", "call"]
|
|
74
|
+
type WidgetTheme = Literal["auto", "light", "dark"]
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
# The provider of the box's own rows (its compute): what the platform cost, beside the vendors'.
|
|
78
|
+
PLATFORM = "pinecall"
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class PromptBlockSpec(WireModel):
|
|
82
|
+
"""One named block of the prompt and the region it lives in."""
|
|
83
|
+
|
|
84
|
+
name: str = Field(pattern="^[a-z][a-z0-9_]*$")
|
|
85
|
+
region: PromptRegion
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class Contact(WireModel):
|
|
89
|
+
"""Who is on the line, as far as the platform knows; a web visitor may be nobody yet."""
|
|
90
|
+
|
|
91
|
+
id: str | None = None
|
|
92
|
+
phone: str | None = None
|
|
93
|
+
name: str | None = None
|
|
94
|
+
email: str | None = None
|
|
95
|
+
external_id: str | None = None
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class Route(WireModel):
|
|
99
|
+
"""One door to an agent: a channel and, for phone and WhatsApp, the number that answers."""
|
|
100
|
+
|
|
101
|
+
channel: Channel
|
|
102
|
+
number: str | None
|
|
103
|
+
label: str | None = None
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
class Supervisor(WireModel):
|
|
107
|
+
"""The human who sent a supervise verb, as the token that let them in names them."""
|
|
108
|
+
|
|
109
|
+
id: str
|
|
110
|
+
name: str | None = None
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
class ToolSpec(WireModel):
|
|
114
|
+
"""What the app declares about one tool."""
|
|
115
|
+
|
|
116
|
+
name: str
|
|
117
|
+
description: str
|
|
118
|
+
parameters: JsonObject
|
|
119
|
+
side_effect: Literal["read", "write", "irreversible"] = "read"
|
|
120
|
+
confirm: str | None = None
|
|
121
|
+
pii: list[str] | None = None
|
|
122
|
+
timeout_s: float | None = None
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
class ToolResult(WireModel):
|
|
126
|
+
"""What came back from running a tool in the app's process: an output or an error."""
|
|
127
|
+
|
|
128
|
+
call_id: str
|
|
129
|
+
name: str
|
|
130
|
+
output: Json = None
|
|
131
|
+
error: str | None = None
|
|
132
|
+
summary: str | None = None
|
|
133
|
+
duration_s: float | None = None
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
class MemoryFact(WireModel):
|
|
137
|
+
"""One thing remembered about a contact."""
|
|
138
|
+
|
|
139
|
+
id: str | None = None
|
|
140
|
+
text: str
|
|
141
|
+
category: str | None = None
|
|
142
|
+
score: float | None = None
|
|
143
|
+
source: str | None = None
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
class MemoryOp(WireModel):
|
|
147
|
+
"""One operation against the contact's memory."""
|
|
148
|
+
|
|
149
|
+
op: Literal["recall", "remember", "forget"]
|
|
150
|
+
contact: str | None = None
|
|
151
|
+
query: str | None = None
|
|
152
|
+
facts: list[MemoryFact]
|
|
153
|
+
took_ms: float
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
class DocSource(WireModel):
|
|
157
|
+
"""One chunk of the knowledge base that retrieval put in front of the model for this turn."""
|
|
158
|
+
|
|
159
|
+
id: str
|
|
160
|
+
base: str | None = None
|
|
161
|
+
path: str
|
|
162
|
+
heading: str | None = None
|
|
163
|
+
score: float
|
|
164
|
+
excerpt: str | None = None
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
class CostRow(WireModel):
|
|
168
|
+
"""One priced line: a model, what was counted, how much, and what it came to."""
|
|
169
|
+
|
|
170
|
+
provider: str
|
|
171
|
+
model: str
|
|
172
|
+
unit: Literal[
|
|
173
|
+
"input_tokens",
|
|
174
|
+
"cached_input_tokens",
|
|
175
|
+
"cache_creation_tokens",
|
|
176
|
+
"output_tokens",
|
|
177
|
+
"characters",
|
|
178
|
+
"audio_seconds",
|
|
179
|
+
"requests",
|
|
180
|
+
"session_seconds",
|
|
181
|
+
"minutes",
|
|
182
|
+
]
|
|
183
|
+
quantity: float
|
|
184
|
+
unit_price_usd: float
|
|
185
|
+
# A summary written before money in dollars priced its rows in euros: the same number, read as
|
|
186
|
+
# dollars and never converted, as migration 0007 kept the facts' column.
|
|
187
|
+
usd: float = Field(validation_alias=AliasChoices("usd", "eur"))
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
class UnpricedRow(WireModel):
|
|
191
|
+
"""A usage row the price table does not know: listed, never priced at zero."""
|
|
192
|
+
|
|
193
|
+
provider: str
|
|
194
|
+
model: str
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
class Cost(WireModel):
|
|
198
|
+
"""What the call cost in provider fees and, priced, the box's own compute; US dollars."""
|
|
199
|
+
|
|
200
|
+
usd: float = Field(validation_alias=AliasChoices("usd", "eur"))
|
|
201
|
+
rows: list[CostRow]
|
|
202
|
+
unpriced: list[UnpricedRow]
|
|
203
|
+
# The euro's rate a summary written before money in dollars carried; read, never written.
|
|
204
|
+
rate: JsonObject | None = Field(default=None, exclude=True)
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
class VoiceConfig(WireModel):
|
|
208
|
+
"""Which voice speaks for the agent."""
|
|
209
|
+
|
|
210
|
+
name: str | None = None
|
|
211
|
+
provider: str | None = None
|
|
212
|
+
model: str | None = None
|
|
213
|
+
voice_id: str | None = None
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
class ModelConfig(WireModel):
|
|
217
|
+
"""Which model does a job (the LLM, or the STT), and the one or two knobs worth turning."""
|
|
218
|
+
|
|
219
|
+
provider: str
|
|
220
|
+
model: str
|
|
221
|
+
temperature: float | None = None
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
class TurnConfig(WireModel):
|
|
225
|
+
"""How the session decides that the caller has finished, and when the caller may interrupt."""
|
|
226
|
+
|
|
227
|
+
min_interruption_words: int | None = None
|
|
228
|
+
endpointing_ms: int | None = None
|
|
229
|
+
eot_threshold: float | None = None
|
|
230
|
+
eager_eot_threshold: float | None = None
|
|
231
|
+
min_interruption_ms: int | None = None
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
class Pronunciation(WireModel):
|
|
235
|
+
"""How the voice says one word it would otherwise get wrong."""
|
|
236
|
+
|
|
237
|
+
word: str
|
|
238
|
+
spoken: str
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
class StateFieldSpec(WireModel):
|
|
242
|
+
"""What the app declares about one field of its state: who may see it."""
|
|
243
|
+
|
|
244
|
+
name: str
|
|
245
|
+
visibility: Visibility
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
class ViewSpec(WireModel):
|
|
249
|
+
"""The panel the agent draws beside a conversation; its contents come by dev verb."""
|
|
250
|
+
|
|
251
|
+
name: str
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
class EventSpec(WireModel):
|
|
255
|
+
"""One outside event the agent accepts, and from whom."""
|
|
256
|
+
|
|
257
|
+
name: str
|
|
258
|
+
from_: list[EventSource] = Field(alias="from")
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
class KnowledgeFile(WireModel):
|
|
262
|
+
"""One file of a base, as a push sends it: its path as the tenant keeps it, and its text."""
|
|
263
|
+
|
|
264
|
+
path: str
|
|
265
|
+
text: str
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
class DocsConfig(WireModel):
|
|
269
|
+
"""The knowledge base the agent answers from, and how its chunks reach the model."""
|
|
270
|
+
|
|
271
|
+
base: str
|
|
272
|
+
mode: DocsMode = "retrieved"
|
|
273
|
+
k: int = 8
|
|
274
|
+
min_score: float | None = None
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
class GreetingConfig(WireModel):
|
|
278
|
+
"""How the agent opens a call: `say` the words, or `reply` what the model reads first."""
|
|
279
|
+
|
|
280
|
+
say: str | None = None
|
|
281
|
+
reply: str | None = None
|
|
282
|
+
allow_interruptions: bool | None = None
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
class HangupConfig(WireModel):
|
|
286
|
+
"""Whether the model may end the call itself, and when."""
|
|
287
|
+
|
|
288
|
+
when: str = ""
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
class MemoryConfig(WireModel):
|
|
292
|
+
"""What memory keeps about a contact across calls, and what it must never keep."""
|
|
293
|
+
|
|
294
|
+
remember: list[str] = Field(default_factory=list[str])
|
|
295
|
+
forget: list[str] = Field(default_factory=list[str])
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
# Every field is optional so a configure can change one thing.
|
|
299
|
+
class AgentConfig(WireModel):
|
|
300
|
+
"""What an app declares about its agent."""
|
|
301
|
+
|
|
302
|
+
prompt: list[PromptBlockSpec] | None = None
|
|
303
|
+
language: str | None = None
|
|
304
|
+
greeting: GreetingConfig | None = None
|
|
305
|
+
voice: VoiceConfig | None = None
|
|
306
|
+
llm: ModelConfig | None = None
|
|
307
|
+
stt: ModelConfig | None = None
|
|
308
|
+
turn: TurnConfig | None = None
|
|
309
|
+
says: list[Pronunciation] | None = None
|
|
310
|
+
hears: list[str] | None = None
|
|
311
|
+
knowledge: KnowledgeFile | None = None
|
|
312
|
+
docs: DocsConfig | None = None
|
|
313
|
+
memory: MemoryConfig | None = None
|
|
314
|
+
hangup: HangupConfig | None = None
|
|
315
|
+
record: bool = True
|
|
316
|
+
tools: list[ToolSpec] | None = None
|
|
317
|
+
uses_knowledge: bool = False
|
|
318
|
+
state_fields: list[StateFieldSpec] | None = None
|
|
319
|
+
view: ViewSpec | None = None
|
|
320
|
+
events: list[EventSpec] | None = None
|
|
File without changes
|