avp-cli 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- avp/__init__.py +31 -0
- avp/commission.py +236 -0
- avp/content.py +273 -0
- avp/data/__init__.py +0 -0
- avp/data/prices.json +21945 -0
- avp/descriptor.py +204 -0
- avp/envelope.py +108 -0
- avp/gen_ai.py +160 -0
- avp/history.py +86 -0
- avp/pricing.py +138 -0
- avp/sink.py +62 -0
- avp/trajectory.py +530 -0
- avp_cli/__init__.py +82 -0
- avp_cli/agent.py +566 -0
- avp_cli/agent_install.py +331 -0
- avp_cli/agent_manifest.py +73 -0
- avp_cli/agents.py +258 -0
- avp_cli/brand.py +46 -0
- avp_cli/broker.py +227 -0
- avp_cli/catalog/__init__.py +128 -0
- avp_cli/catalog/capitals.json +67 -0
- avp_cli/catalog/custom.json +35 -0
- avp_cli/catalog/parsebench.json +44 -0
- avp_cli/cli.py +1858 -0
- avp_cli/commission.py +144 -0
- avp_cli/config.py +250 -0
- avp_cli/console.py +51 -0
- avp_cli/environment.py +218 -0
- avp_cli/eval/__init__.py +0 -0
- avp_cli/eval/dataset.py +37 -0
- avp_cli/eval/engine.py +426 -0
- avp_cli/eval/report.py +178 -0
- avp_cli/eval/scoring.py +260 -0
- avp_cli/eval/setup.py +69 -0
- avp_cli/images.py +119 -0
- avp_cli/library.py +95 -0
- avp_cli/live.py +185 -0
- avp_cli/observability.py +128 -0
- avp_cli/onboarding.py +80 -0
- avp_cli/osb.py +347 -0
- avp_cli/paths.py +47 -0
- avp_cli/run_manifest.py +113 -0
- avp_cli/state.py +195 -0
- avp_cli/vault.py +116 -0
- avp_cli/viz.py +303 -0
- avp_cli-0.1.0.dist-info/METADATA +359 -0
- avp_cli-0.1.0.dist-info/RECORD +49 -0
- avp_cli-0.1.0.dist-info/WHEEL +4 -0
- avp_cli-0.1.0.dist-info/entry_points.txt +2 -0
avp/__init__.py
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""avp — Python reference implementation for the Agent Voyager Project (v0.1 model).
|
|
2
|
+
|
|
3
|
+
The wire format is built on CloudEvents 1.0, OpenTelemetry GenAI semantic
|
|
4
|
+
conventions, OTel spans, JSON-RPC 2.0, MCP, Agent Skills, and JSON Schema.
|
|
5
|
+
See FOUNDATIONS.md for the full mapping.
|
|
6
|
+
|
|
7
|
+
Public API lives in the spec-scoped submodules; this package's top level
|
|
8
|
+
exposes only version metadata. Import wire types and helpers directly from
|
|
9
|
+
the module that owns them:
|
|
10
|
+
|
|
11
|
+
from avp.commission import Commission, McpServerHttp, McpServerStdio, Skill
|
|
12
|
+
from avp.descriptor import AgentDescriptor
|
|
13
|
+
from avp.trajectory import (
|
|
14
|
+
AgentStartedEvent,
|
|
15
|
+
Event,
|
|
16
|
+
parse_event,
|
|
17
|
+
event_to_wire,
|
|
18
|
+
)
|
|
19
|
+
from avp.tracer import AVPTracer, current_tracer
|
|
20
|
+
from avp.io import iter_events, write_event
|
|
21
|
+
from avp.enums import ErrorCode, StopReason
|
|
22
|
+
from avp.pricing import compute_cost, load_default_prices
|
|
23
|
+
|
|
24
|
+
Doing it this way keeps the spec ↔ module mapping 1:1 and prevents drift
|
|
25
|
+
into a single "everything-bag" import surface.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
__version__ = "0.1.0"
|
|
29
|
+
SCHEMA_VERSION = "0.1"
|
|
30
|
+
|
|
31
|
+
__all__ = ["SCHEMA_VERSION", "__version__"]
|
avp/commission.py
ADDED
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
"""avp.commission — Pydantic types for the AVP Commission Spec.
|
|
2
|
+
|
|
3
|
+
Defines the Commission shape (supervisor → agent setup message) and the
|
|
4
|
+
managed-asset entries the supervisor declares inline. This module mirrors
|
|
5
|
+
the [Commission spec](../../../../spec/v0.1/commission.md).
|
|
6
|
+
|
|
7
|
+
Consumers wanting only the run-config object can:
|
|
8
|
+
|
|
9
|
+
from avp.commission import Commission, McpServerHttp, McpServerStdio
|
|
10
|
+
|
|
11
|
+
…without dragging in Trajectory / Descriptor types.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
from typing import Annotated, Any, Literal
|
|
17
|
+
|
|
18
|
+
from pydantic import BaseModel, Field, field_validator
|
|
19
|
+
|
|
20
|
+
from avp.envelope import _STRICT
|
|
21
|
+
|
|
22
|
+
_ID_PATTERN = r"^[a-z0-9_-]+$"
|
|
23
|
+
|
|
24
|
+
# `model` is a canonical models.dev slug: "<origin>/<model>" (e.g.
|
|
25
|
+
# "anthropic/claude-opus-4-8", "openai/gpt-4o"). The origin segment is the
|
|
26
|
+
# model's home namespace and the pricing key; it is independent of the
|
|
27
|
+
# `Provider.id` storefront that actually serves the tokens.
|
|
28
|
+
_MODEL_SLUG_PATTERN = r"^[^/]+/.+$"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class SecretRef(BaseModel):
|
|
32
|
+
"""A reference to a secret the supervisor resolves out of band.
|
|
33
|
+
|
|
34
|
+
Carries a `vault` handle, never the secret value. The supervisor maps the
|
|
35
|
+
handle to material (env var, secrets file, broker) at run time; the value
|
|
36
|
+
never appears on the wire or in the trajectory. Used by `Provider.credential`
|
|
37
|
+
and `McpServerHttp.auth`.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
model_config = _STRICT
|
|
41
|
+
vault: str = Field(min_length=1, pattern=_ID_PATTERN)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class McpServerHttp(BaseModel):
|
|
45
|
+
"""Inline HTTP MCP server entry in Commission.mcp_servers."""
|
|
46
|
+
|
|
47
|
+
model_config = _STRICT
|
|
48
|
+
id: str = Field(min_length=1, pattern=_ID_PATTERN)
|
|
49
|
+
type: Literal["http"]
|
|
50
|
+
url: str = Field(min_length=1)
|
|
51
|
+
# Non-secret request headers. Credentials go in `auth` (a SecretRef the
|
|
52
|
+
# supervisor resolves out of band), not here.
|
|
53
|
+
headers: dict[str, str] | None = None
|
|
54
|
+
auth: SecretRef | None = None
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class McpServerStdio(BaseModel):
|
|
58
|
+
"""Inline stdio MCP server entry in Commission.mcp_servers."""
|
|
59
|
+
|
|
60
|
+
model_config = _STRICT
|
|
61
|
+
id: str = Field(min_length=1, pattern=_ID_PATTERN)
|
|
62
|
+
type: Literal["stdio"]
|
|
63
|
+
command: list[str] = Field(min_length=1)
|
|
64
|
+
args: list[str] | None = None
|
|
65
|
+
env: dict[str, str] | None = None
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
McpServer = Annotated[McpServerHttp | McpServerStdio, Field(discriminator="type")]
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class Provider(BaseModel):
|
|
72
|
+
"""Optional LLM routing override: which storefront serves the model.
|
|
73
|
+
|
|
74
|
+
Absent → the agent uses its native default (whatever its own environment
|
|
75
|
+
configures). Present → the supervisor directs the agent at a specific
|
|
76
|
+
endpoint. `id` selects the protocol/auth family (e.g. "anthropic",
|
|
77
|
+
"openai", "openrouter"); `base_url` overrides the endpoint; `credential`
|
|
78
|
+
references the API key by vault handle (never the value).
|
|
79
|
+
|
|
80
|
+
The model's origin (the `Commission.model` slug's first segment) and the
|
|
81
|
+
storefront `id` are independent axes: `model: "openai/gpt-4o"` with
|
|
82
|
+
`provider.id: "openrouter"` reads as "OpenAI's gpt-4o, bought through
|
|
83
|
+
OpenRouter". An agent that cannot speak the requested provider's protocol
|
|
84
|
+
MUST fail (error_occurred + agent_stopped reason=error), never silently
|
|
85
|
+
run elsewhere.
|
|
86
|
+
"""
|
|
87
|
+
|
|
88
|
+
model_config = _STRICT
|
|
89
|
+
id: str = Field(min_length=1, pattern=_ID_PATTERN)
|
|
90
|
+
base_url: str | None = None
|
|
91
|
+
credential: SecretRef | None = None
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class Skill(BaseModel):
|
|
95
|
+
"""Inline skill entry in Commission.skills."""
|
|
96
|
+
|
|
97
|
+
model_config = _STRICT
|
|
98
|
+
id: str = Field(min_length=1, pattern=_ID_PATTERN)
|
|
99
|
+
files: dict[str, str]
|
|
100
|
+
|
|
101
|
+
@field_validator("files")
|
|
102
|
+
@classmethod
|
|
103
|
+
def _require_skill_md(cls, v: dict[str, str]) -> dict[str, str]:
|
|
104
|
+
if "SKILL.md" not in v:
|
|
105
|
+
raise ValueError("files must contain 'SKILL.md'")
|
|
106
|
+
return v
|
|
107
|
+
|
|
108
|
+
def _frontmatter_value(self, key: str) -> str | None:
|
|
109
|
+
content = self.files.get("SKILL.md", "")
|
|
110
|
+
if not content.startswith("---"):
|
|
111
|
+
return None
|
|
112
|
+
end = content.find("---", 3)
|
|
113
|
+
if end == -1:
|
|
114
|
+
return None
|
|
115
|
+
for line in content[3:end].splitlines():
|
|
116
|
+
if line.startswith(f"{key}:"):
|
|
117
|
+
return line[len(key) + 1 :].strip() or None
|
|
118
|
+
return None
|
|
119
|
+
|
|
120
|
+
@property
|
|
121
|
+
def name(self) -> str | None:
|
|
122
|
+
return self._frontmatter_value("name")
|
|
123
|
+
|
|
124
|
+
@property
|
|
125
|
+
def description(self) -> str | None:
|
|
126
|
+
return self._frontmatter_value("description")
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
class SupervisorPreamble(BaseModel):
|
|
130
|
+
"""Identifies the supervisor that is requesting the run.
|
|
131
|
+
|
|
132
|
+
Carried inside `Commission.supervisor` and projected onto the
|
|
133
|
+
`run_requested` event's `data` (`avp.supervisor.name` +
|
|
134
|
+
`avp.supervisor.version`) so a trajectory consumer can attribute the
|
|
135
|
+
run to the originating supervisor without an out-of-band lookup. The
|
|
136
|
+
event's `source` is `avp://agent` (the agent is the sole producer on
|
|
137
|
+
the wire); supervisor attribution lives inside `data`.
|
|
138
|
+
|
|
139
|
+
`name` SHOULD be a stable identifier for the supervisor implementation
|
|
140
|
+
or instance (e.g. `"avp-cli"`, `"acme.scheduler"`).
|
|
141
|
+
`version` is optional but recommended; it travels with the trajectory
|
|
142
|
+
and lets auditors correlate a run with the exact supervisor build
|
|
143
|
+
that requested it.
|
|
144
|
+
"""
|
|
145
|
+
|
|
146
|
+
model_config = _STRICT
|
|
147
|
+
name: str = Field(min_length=1)
|
|
148
|
+
version: str | None = None
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
class Commission(BaseModel):
|
|
152
|
+
"""Supervisor's declaration of the supervisor-managed environment slice.
|
|
153
|
+
|
|
154
|
+
Managed asset entries (`mcp_servers`, `skills`) carry inline connection
|
|
155
|
+
material; no resolver round-trip is needed. The agent dials MCP servers
|
|
156
|
+
and injects skill content directly from these fields at startup.
|
|
157
|
+
|
|
158
|
+
Anything the agent provides on its own (in-process tools, baked-in
|
|
159
|
+
skills) is invisible to AVP and the Commission entirely. The agent's own
|
|
160
|
+
contribution surfaces in `agent_described.data["avp.descriptor"]` so
|
|
161
|
+
consumers can audit what the agent showed up with. The agent's runtime
|
|
162
|
+
layer merges its internal contribution with the Commission-managed assets
|
|
163
|
+
into one bag the loop dispatches against; collisions on `id` are a
|
|
164
|
+
startup error.
|
|
165
|
+
"""
|
|
166
|
+
|
|
167
|
+
model_config = _STRICT
|
|
168
|
+
|
|
169
|
+
schema_version: Literal["0.1"]
|
|
170
|
+
run_id: str = Field(min_length=1)
|
|
171
|
+
|
|
172
|
+
# Supervisor identity. Optional but RECOMMENDED. When present, the agent
|
|
173
|
+
# stamps `run_requested.data.avp.supervisor.*` from this field so the
|
|
174
|
+
# trajectory records who requested the run. When absent, the agent
|
|
175
|
+
# still emits `run_requested` but with `avp.supervisor.name="unknown"`.
|
|
176
|
+
supervisor: SupervisorPreamble | None = None
|
|
177
|
+
|
|
178
|
+
# Supervisor-managed assets. Connection material is inline; agents dial
|
|
179
|
+
# MCP servers and load skill content directly at startup.
|
|
180
|
+
mcp_servers: list[McpServer] | None = None
|
|
181
|
+
skills: list[Skill] | None = None
|
|
182
|
+
|
|
183
|
+
# Optional LLM routing override. Absent → the agent's native default.
|
|
184
|
+
provider: Provider | None = None
|
|
185
|
+
|
|
186
|
+
# Allow-lists over the agent's Descriptor-declared surface. Each list
|
|
187
|
+
# gates the parallel `descriptor.*` field for this run.
|
|
188
|
+
#
|
|
189
|
+
# - None (absent) → every descriptor entry of that kind is exposed
|
|
190
|
+
# (default).
|
|
191
|
+
# - [] → none are exposed.
|
|
192
|
+
# - [n1, n2, …] → only the listed names/ids are exposed; the agent
|
|
193
|
+
# hides the rest from the model and runtime-blocks
|
|
194
|
+
# any hallucinated invocation with a `tool_returned`
|
|
195
|
+
# (isError=True) (or, for subagents, a
|
|
196
|
+
# `subagent_returned` with `reason=error`).
|
|
197
|
+
#
|
|
198
|
+
# Names MUST appear in the corresponding descriptor field at startup or
|
|
199
|
+
# the agent emits `error_occurred(code: "commission_collision")` and
|
|
200
|
+
# stops with `reason=error`. Subtractive-only: these have no effect on
|
|
201
|
+
# supervisor-managed assets (those are gated by being-in-the-Commission).
|
|
202
|
+
# `enabled_builtin_mcp_servers` filters `descriptor.mcp_servers[].id`;
|
|
203
|
+
# disabling a server prevents the agent from dialing it, so its tools
|
|
204
|
+
# are unavailable for the run.
|
|
205
|
+
enabled_builtin_tools: list[str] | None = None
|
|
206
|
+
enabled_builtin_subagents: list[str] | None = None
|
|
207
|
+
enabled_builtin_skills: list[str] | None = None
|
|
208
|
+
enabled_builtin_mcp_servers: list[str] | None = None
|
|
209
|
+
|
|
210
|
+
output_schema: dict[str, Any] | None = None
|
|
211
|
+
|
|
212
|
+
# Agent plane (what the agent runs)
|
|
213
|
+
prompt: str | None = None
|
|
214
|
+
system_prompt: str | None = None
|
|
215
|
+
# Canonical models.dev slug "<origin>/<model>" (e.g. "anthropic/claude-opus-4-8").
|
|
216
|
+
# The pattern requires a non-empty origin and model id. Required: the origin
|
|
217
|
+
# segment is the pricing key and the native-default routing hint; agents
|
|
218
|
+
# split it off to get the SDK-native model id.
|
|
219
|
+
model: str = Field(min_length=1, pattern=_MODEL_SLUG_PATTERN)
|
|
220
|
+
|
|
221
|
+
# Metadata
|
|
222
|
+
thread_id: str | None = None
|
|
223
|
+
tags: list[str] | None = None
|
|
224
|
+
meta: dict[str, Any] | None = None
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
__all__ = [
|
|
228
|
+
"Commission",
|
|
229
|
+
"McpServer",
|
|
230
|
+
"McpServerHttp",
|
|
231
|
+
"McpServerStdio",
|
|
232
|
+
"Provider",
|
|
233
|
+
"SecretRef",
|
|
234
|
+
"Skill",
|
|
235
|
+
"SupervisorPreamble",
|
|
236
|
+
]
|
avp/content.py
ADDED
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
"""avp.content — AVP content block types for assistant message content.
|
|
2
|
+
|
|
3
|
+
Normalized content union covering the message-history shapes of Anthropic
|
|
4
|
+
Messages, OpenAI Chat Completions + Responses, Google Gemini
|
|
5
|
+
generateContent, AWS Bedrock Converse, Cohere Chat, and Mistral Chat.
|
|
6
|
+
The goal is non-lossy round-trip of agent history across providers.
|
|
7
|
+
|
|
8
|
+
Every block sets `model_config = ConfigDict(extra="allow")` so unmodeled
|
|
9
|
+
provider-specific fields (Anthropic `cache_control`, OpenAI
|
|
10
|
+
`encrypted_content`, Gemini `thought_signature`, future additions)
|
|
11
|
+
round-trip unchanged without spec churn.
|
|
12
|
+
|
|
13
|
+
Discriminate on the `type` field. Serialize with
|
|
14
|
+
`model_dump(by_alias=True, mode="json")`.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
from typing import Annotated, Any, Literal
|
|
20
|
+
|
|
21
|
+
from pydantic import BaseModel, Field
|
|
22
|
+
|
|
23
|
+
from avp.envelope import _OPEN
|
|
24
|
+
|
|
25
|
+
# ── Source variants ───────────────────────────────────────────────────────────
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class Base64Source(BaseModel):
|
|
29
|
+
"""Inline base64-encoded media. Anthropic `source.type=base64`, Gemini
|
|
30
|
+
`inline_data`, Bedrock `source.bytes`."""
|
|
31
|
+
|
|
32
|
+
model_config = _OPEN
|
|
33
|
+
type: Literal["base64"] = "base64"
|
|
34
|
+
media_type: str
|
|
35
|
+
data: str
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class UrlSource(BaseModel):
|
|
39
|
+
"""External URL. Anthropic `source.type=url`, OpenAI `image_url`,
|
|
40
|
+
Gemini `file_data` (when `file_uri` is a public URL)."""
|
|
41
|
+
|
|
42
|
+
model_config = _OPEN
|
|
43
|
+
type: Literal["url"] = "url"
|
|
44
|
+
url: str
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class FileSource(BaseModel):
|
|
48
|
+
"""Provider-hosted file reference. OpenAI Files API `file_id`, Anthropic
|
|
49
|
+
Files API `file_id`, Gemini `file_data.file_uri` (Files API URI)."""
|
|
50
|
+
|
|
51
|
+
model_config = _OPEN
|
|
52
|
+
type: Literal["file"] = "file"
|
|
53
|
+
file_id: str
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
Source = Annotated[Base64Source | UrlSource | FileSource, Field(discriminator="type")]
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
# ── Citations / annotations ───────────────────────────────────────────────────
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class Citation(BaseModel):
|
|
63
|
+
"""Span-anchored attribution on a text or document block. Unifies
|
|
64
|
+
Anthropic citations (`char_location`, `page_location`,
|
|
65
|
+
`content_block_location`), OpenAI annotations (`url_citation`,
|
|
66
|
+
`file_citation`, `file_path`), and Gemini grounding chunks. `type`
|
|
67
|
+
carries the provider's raw citation kind verbatim so downstream
|
|
68
|
+
consumers can normalize without re-deriving it."""
|
|
69
|
+
|
|
70
|
+
model_config = _OPEN
|
|
71
|
+
type: str
|
|
72
|
+
cited_text: str | None = None
|
|
73
|
+
start_index: int | None = Field(default=None, ge=0)
|
|
74
|
+
end_index: int | None = Field(default=None, ge=0)
|
|
75
|
+
source_id: str | None = None
|
|
76
|
+
source_url: str | None = None
|
|
77
|
+
source_title: str | None = None
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
# ── Blocks ────────────────────────────────────────────────────────────────────
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class TextBlock(BaseModel):
|
|
84
|
+
"""Plain text content. Anthropic `text`, OpenAI `text` /
|
|
85
|
+
`output_text` / `input_text`, Gemini text part, Bedrock `text`,
|
|
86
|
+
Cohere `text`, Mistral `text`. `citations` carries Anthropic citations,
|
|
87
|
+
OpenAI annotations, and Gemini grounding spans anchored into this text."""
|
|
88
|
+
|
|
89
|
+
model_config = _OPEN
|
|
90
|
+
type: Literal["text"] = "text"
|
|
91
|
+
text: str
|
|
92
|
+
citations: list[Citation] | None = None
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class ThinkingBlock(BaseModel):
|
|
96
|
+
"""Reasoning / chain-of-thought emitted by the model.
|
|
97
|
+
|
|
98
|
+
Anthropic extended thinking, OpenAI o-series `reasoning` items,
|
|
99
|
+
Gemini `thought` parts, Bedrock `reasoningContent`, Mistral thinking.
|
|
100
|
+
`signature` is the opaque blob the provider requires echoed back on
|
|
101
|
+
the next turn for continued reasoning: Anthropic's cryptographic
|
|
102
|
+
signature, OpenAI's `encrypted_content`, or Gemini's
|
|
103
|
+
`thought_signature`. `redacted` flags blocks whose plaintext is
|
|
104
|
+
unavailable (encrypted-only form)."""
|
|
105
|
+
|
|
106
|
+
model_config = _OPEN
|
|
107
|
+
type: Literal["thinking"] = "thinking"
|
|
108
|
+
thinking: str
|
|
109
|
+
signature: str | None = None
|
|
110
|
+
redacted: bool | None = None
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
class ImageBlock(BaseModel):
|
|
114
|
+
"""Image content. Anthropic `image`, OpenAI `image_url` /
|
|
115
|
+
`input_image`, Gemini `inline_data` / `file_data` image, Bedrock
|
|
116
|
+
`image`."""
|
|
117
|
+
|
|
118
|
+
model_config = _OPEN
|
|
119
|
+
type: Literal["image"] = "image"
|
|
120
|
+
source: Source
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class AudioBlock(BaseModel):
|
|
124
|
+
"""Audio content. OpenAI `input_audio` (input) and `audio` (output),
|
|
125
|
+
Gemini `inline_data` audio, Bedrock `audio`. `transcript` carries
|
|
126
|
+
OpenAI's output-audio transcript when present."""
|
|
127
|
+
|
|
128
|
+
model_config = _OPEN
|
|
129
|
+
type: Literal["audio"] = "audio"
|
|
130
|
+
source: Source
|
|
131
|
+
transcript: str | None = None
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
class VideoBlock(BaseModel):
|
|
135
|
+
"""Video content. Gemini `inline_data` / `file_data` video, Bedrock
|
|
136
|
+
`video`."""
|
|
137
|
+
|
|
138
|
+
model_config = _OPEN
|
|
139
|
+
type: Literal["video"] = "video"
|
|
140
|
+
source: Source
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
class DocumentBlock(BaseModel):
|
|
144
|
+
"""Document / file content (typically PDFs). Anthropic `document`
|
|
145
|
+
(with citation support), OpenAI `input_file`, Gemini `file_data`,
|
|
146
|
+
Bedrock `document`. `title` is the document name used as the
|
|
147
|
+
citation target; `context` is supplementary metadata Anthropic
|
|
148
|
+
surfaces alongside the document for the model."""
|
|
149
|
+
|
|
150
|
+
model_config = _OPEN
|
|
151
|
+
type: Literal["document"] = "document"
|
|
152
|
+
source: Source
|
|
153
|
+
title: str | None = None
|
|
154
|
+
context: str | None = None
|
|
155
|
+
citations: list[Citation] | None = None
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
class ToolUseBlock(BaseModel):
|
|
159
|
+
"""Model invokes a client-dispatched tool. Anthropic `tool_use`,
|
|
160
|
+
OpenAI `function_call` / `tool_calls`, Gemini `function_call`,
|
|
161
|
+
Bedrock `toolUse`, Cohere tool_calls, Mistral tool_calls."""
|
|
162
|
+
|
|
163
|
+
model_config = _OPEN
|
|
164
|
+
type: Literal["tool_use"] = "tool_use"
|
|
165
|
+
id: str
|
|
166
|
+
name: str
|
|
167
|
+
input: dict[str, Any]
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
ToolResultContent = Annotated[TextBlock | ImageBlock | DocumentBlock, Field(discriminator="type")]
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
class ToolResultBlock(BaseModel):
|
|
174
|
+
"""Result of a client-dispatched tool call. Anthropic `tool_result`,
|
|
175
|
+
OpenAI `function_call_output` / tool-role message, Gemini
|
|
176
|
+
`function_response`, Bedrock `toolResult`. Anthropic permits nested
|
|
177
|
+
text/image/document content blocks; other providers serialize a
|
|
178
|
+
flat string. `structured_content` carries a programmatic payload
|
|
179
|
+
alongside the human-readable `content` (MCP's `structuredContent`,
|
|
180
|
+
Gemini `function_response.response`, Bedrock `toolResult.content.json`);
|
|
181
|
+
the two channels are complementary, not alternatives. `is_error`
|
|
182
|
+
flags rejections."""
|
|
183
|
+
|
|
184
|
+
model_config = _OPEN
|
|
185
|
+
type: Literal["tool_result"] = "tool_result"
|
|
186
|
+
tool_use_id: str
|
|
187
|
+
content: str | list[ToolResultContent]
|
|
188
|
+
structured_content: dict[str, Any] | None = None
|
|
189
|
+
is_error: bool | None = None
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
class ServerToolUseBlock(BaseModel):
|
|
193
|
+
"""Built-in tool executed by the provider rather than the agent.
|
|
194
|
+
Anthropic `server_tool_use` (web_search, code_execution), OpenAI
|
|
195
|
+
Responses `web_search_call` / `file_search_call` / `computer_call` /
|
|
196
|
+
`code_interpreter_call`, Gemini `executable_code` / `google_search`.
|
|
197
|
+
`name` carries the tool kind (e.g. "web_search", "code_interpreter",
|
|
198
|
+
"computer_use", "google_search"). Distinct from `tool_use` because
|
|
199
|
+
the agent never dispatches these; they are observability of a
|
|
200
|
+
provider-side action."""
|
|
201
|
+
|
|
202
|
+
model_config = _OPEN
|
|
203
|
+
type: Literal["server_tool_use"] = "server_tool_use"
|
|
204
|
+
id: str
|
|
205
|
+
name: str
|
|
206
|
+
input: dict[str, Any]
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
class ServerToolResultBlock(BaseModel):
|
|
210
|
+
"""Result of a provider-executed built-in tool. Pairs with
|
|
211
|
+
`ServerToolUseBlock`. Anthropic `web_search_tool_result`, OpenAI
|
|
212
|
+
Responses `*_call_output`, Gemini `code_execution_result`.
|
|
213
|
+
`content` is provider-shaped (search-result rows, code stdout,
|
|
214
|
+
computer-use screenshots, ...)."""
|
|
215
|
+
|
|
216
|
+
model_config = _OPEN
|
|
217
|
+
type: Literal["server_tool_result"] = "server_tool_result"
|
|
218
|
+
tool_use_id: str
|
|
219
|
+
name: str
|
|
220
|
+
content: Any
|
|
221
|
+
is_error: bool | None = None
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
class RefusalBlock(BaseModel):
|
|
225
|
+
"""Structured refusal distinct from generated text. OpenAI assistant
|
|
226
|
+
message `refusal` field and Responses `output_refusal` item. Other
|
|
227
|
+
providers emit refusals as plain text plus a finish reason; this
|
|
228
|
+
block represents only providers that ship a typed refusal."""
|
|
229
|
+
|
|
230
|
+
model_config = _OPEN
|
|
231
|
+
type: Literal["refusal"] = "refusal"
|
|
232
|
+
refusal: str
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
# ── Discriminated union ───────────────────────────────────────────────────────
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
AVPContentBlock = Annotated[
|
|
239
|
+
TextBlock
|
|
240
|
+
| ThinkingBlock
|
|
241
|
+
| ImageBlock
|
|
242
|
+
| AudioBlock
|
|
243
|
+
| VideoBlock
|
|
244
|
+
| DocumentBlock
|
|
245
|
+
| ToolUseBlock
|
|
246
|
+
| ToolResultBlock
|
|
247
|
+
| ServerToolUseBlock
|
|
248
|
+
| ServerToolResultBlock
|
|
249
|
+
| RefusalBlock,
|
|
250
|
+
Field(discriminator="type"),
|
|
251
|
+
]
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
__all__ = [
|
|
255
|
+
"AVPContentBlock",
|
|
256
|
+
"AudioBlock",
|
|
257
|
+
"Base64Source",
|
|
258
|
+
"Citation",
|
|
259
|
+
"DocumentBlock",
|
|
260
|
+
"FileSource",
|
|
261
|
+
"ImageBlock",
|
|
262
|
+
"RefusalBlock",
|
|
263
|
+
"ServerToolResultBlock",
|
|
264
|
+
"ServerToolUseBlock",
|
|
265
|
+
"Source",
|
|
266
|
+
"TextBlock",
|
|
267
|
+
"ThinkingBlock",
|
|
268
|
+
"ToolResultBlock",
|
|
269
|
+
"ToolResultContent",
|
|
270
|
+
"ToolUseBlock",
|
|
271
|
+
"UrlSource",
|
|
272
|
+
"VideoBlock",
|
|
273
|
+
]
|
avp/data/__init__.py
ADDED
|
File without changes
|