livekit-plugins-anthropic 0.2.6__py3-none-any.whl → 0.2.8__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.
@@ -24,8 +24,8 @@ from typing import (
24
24
  Awaitable,
25
25
  List,
26
26
  Literal,
27
- Tuple,
28
27
  Union,
28
+ cast,
29
29
  get_args,
30
30
  get_origin,
31
31
  )
@@ -40,6 +40,10 @@ from livekit.agents import (
40
40
  utils,
41
41
  )
42
42
  from livekit.agents.llm import ToolChoice
43
+ from livekit.agents.llm.function_context import (
44
+ _create_ai_function_info,
45
+ _is_optional_type,
46
+ )
43
47
  from livekit.agents.types import DEFAULT_API_CONNECT_OPTIONS, APIConnectOptions
44
48
 
45
49
  import anthropic
@@ -402,8 +406,10 @@ def _build_anthropic_message(
402
406
 
403
407
  return a_msg
404
408
  elif msg.role == "tool":
409
+ if isinstance(msg.content, dict):
410
+ msg.content = json.dumps(msg.content)
405
411
  if not isinstance(msg.content, str):
406
- logger.warning("tool message content is not a string")
412
+ logger.warning("tool message content is not a string or dict")
407
413
  return None
408
414
  if not msg.tool_call_id:
409
415
  return None
@@ -425,11 +431,36 @@ def _build_anthropic_message(
425
431
  def _build_anthropic_image_content(
426
432
  image: llm.ChatImage, cache_key: Any
427
433
  ) -> anthropic.types.ImageBlockParam:
428
- if isinstance(image.image, str): # image url
429
- logger.warning(
430
- "image url not supported by anthropic, skipping image '%s'", image.image
431
- )
432
- elif isinstance(image.image, rtc.VideoFrame): # VideoFrame
434
+ if isinstance(image.image, str): # image is a URL
435
+ if not image.image.startswith("data:"):
436
+ raise ValueError("LiveKit Anthropic Plugin: Image URLs must be data URLs")
437
+
438
+ try:
439
+ header, b64_data = image.image.split(",", 1)
440
+ media_type = header.split(";")[0].split(":")[1]
441
+
442
+ supported_types = {"image/jpeg", "image/png", "image/webp", "image/gif"}
443
+ if media_type not in supported_types:
444
+ raise ValueError(
445
+ f"LiveKit Anthropic Plugin: Unsupported media type {media_type}. Must be jpeg, png, webp, or gif"
446
+ )
447
+
448
+ return {
449
+ "type": "image",
450
+ "source": {
451
+ "type": "base64",
452
+ "data": b64_data,
453
+ "media_type": cast(
454
+ Literal["image/jpeg", "image/png", "image/gif", "image/webp"],
455
+ media_type,
456
+ ),
457
+ },
458
+ }
459
+ except (ValueError, IndexError) as e:
460
+ raise ValueError(
461
+ f"LiveKit Anthropic Plugin: Invalid image data URL {str(e)}"
462
+ )
463
+ elif isinstance(image.image, rtc.VideoFrame): # image is a VideoFrame
433
464
  if cache_key not in image._cache:
434
465
  # inside our internal implementation, we allow to put extra metadata to
435
466
  # each ChatImage (avoid to reencode each time we do a chatcompletion request)
@@ -438,7 +469,7 @@ def _build_anthropic_image_content(
438
469
  opts.resize_options = utils.images.ResizeOptions(
439
470
  width=image.inference_width,
440
471
  height=image.inference_height,
441
- strategy="center_aspect_fit",
472
+ strategy="scale_aspect_fit",
442
473
  )
443
474
 
444
475
  encoded_data = utils.images.encode(image.image, opts)
@@ -453,65 +484,8 @@ def _build_anthropic_image_content(
453
484
  },
454
485
  }
455
486
 
456
- raise ValueError(f"unknown image type {type(image.image)}")
457
-
458
-
459
- def _create_ai_function_info(
460
- fnc_ctx: llm.function_context.FunctionContext,
461
- tool_call_id: str,
462
- fnc_name: str,
463
- raw_arguments: str, # JSON string
464
- ) -> llm.function_context.FunctionCallInfo:
465
- if fnc_name not in fnc_ctx.ai_functions:
466
- raise ValueError(f"AI function {fnc_name} not found")
467
-
468
- parsed_arguments: dict[str, Any] = {}
469
- try:
470
- if raw_arguments: # ignore empty string
471
- parsed_arguments = json.loads(raw_arguments)
472
- except json.JSONDecodeError:
473
- raise ValueError(
474
- f"AI function {fnc_name} received invalid JSON arguments - {raw_arguments}"
475
- )
476
-
477
- fnc_info = fnc_ctx.ai_functions[fnc_name]
478
-
479
- # Ensure all necessary arguments are present and of the correct type.
480
- sanitized_arguments: dict[str, Any] = {}
481
- for arg_info in fnc_info.arguments.values():
482
- if arg_info.name not in parsed_arguments:
483
- if arg_info.default is inspect.Parameter.empty:
484
- raise ValueError(
485
- f"AI function {fnc_name} missing required argument {arg_info.name}"
486
- )
487
- continue
488
-
489
- arg_value = parsed_arguments[arg_info.name]
490
- if get_origin(arg_info.type) is not None:
491
- if not isinstance(arg_value, list):
492
- raise ValueError(
493
- f"AI function {fnc_name} argument {arg_info.name} should be a list"
494
- )
495
-
496
- inner_type = get_args(arg_info.type)[0]
497
- sanitized_value = [
498
- _sanitize_primitive(
499
- value=v, expected_type=inner_type, choices=arg_info.choices
500
- )
501
- for v in arg_value
502
- ]
503
- else:
504
- sanitized_value = _sanitize_primitive(
505
- value=arg_value, expected_type=arg_info.type, choices=arg_info.choices
506
- )
507
-
508
- sanitized_arguments[arg_info.name] = sanitized_value
509
-
510
- return llm.function_context.FunctionCallInfo(
511
- tool_call_id=tool_call_id,
512
- raw_arguments=raw_arguments,
513
- function_info=fnc_info,
514
- arguments=sanitized_arguments,
487
+ raise ValueError(
488
+ "LiveKit Anthropic Plugin: ChatImage must be an rtc.VideoFrame or a data URL"
515
489
  )
516
490
 
517
491
 
@@ -538,8 +512,10 @@ def _build_function_description(
538
512
  if arg_info.description:
539
513
  p["description"] = arg_info.description
540
514
 
541
- if get_origin(arg_info.type) is list:
542
- inner_type = get_args(arg_info.type)[0]
515
+ is_optional, inner_th = _is_optional_type(arg_info.type)
516
+
517
+ if get_origin(inner_th) is list:
518
+ inner_type = get_args(inner_th)[0]
543
519
  p["type"] = "array"
544
520
  p["items"] = {}
545
521
  p["items"]["type"] = type2str(inner_type)
@@ -547,7 +523,7 @@ def _build_function_description(
547
523
  if arg_info.choices:
548
524
  p["items"]["enum"] = arg_info.choices
549
525
  else:
550
- p["type"] = type2str(arg_info.type)
526
+ p["type"] = type2str(inner_th)
551
527
  if arg_info.choices:
552
528
  p["enum"] = arg_info.choices
553
529
 
@@ -563,31 +539,3 @@ def _build_function_description(
563
539
  "description": fnc_info.description,
564
540
  "input_schema": input_schema,
565
541
  }
566
-
567
-
568
- def _sanitize_primitive(
569
- *, value: Any, expected_type: type, choices: Tuple[Any] | None
570
- ) -> Any:
571
- if expected_type is str:
572
- if not isinstance(value, str):
573
- raise ValueError(f"expected str, got {type(value)}")
574
- elif expected_type in (int, float):
575
- if not isinstance(value, (int, float)):
576
- raise ValueError(f"expected number, got {type(value)}")
577
-
578
- if expected_type is int:
579
- if value % 1 != 0:
580
- raise ValueError("expected int, got float")
581
-
582
- value = int(value)
583
- elif expected_type is float:
584
- value = float(value)
585
-
586
- elif expected_type is bool:
587
- if not isinstance(value, bool):
588
- raise ValueError(f"expected bool, got {type(value)}")
589
-
590
- if choices and value not in choices:
591
- raise ValueError(f"invalid value {value}, not in {choices}")
592
-
593
- return value
@@ -12,4 +12,4 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- __version__ = "0.2.6"
15
+ __version__ = "0.2.8"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: livekit-plugins-anthropic
3
- Version: 0.2.6
3
+ Version: 0.2.8
4
4
  Summary: Agent Framework plugin for services from Anthropic
5
5
  Home-page: https://github.com/livekit/agents
6
6
  License: Apache-2.0
@@ -19,7 +19,7 @@ Classifier: Programming Language :: Python :: 3.10
19
19
  Classifier: Programming Language :: Python :: 3 :: Only
20
20
  Requires-Python: >=3.9.0
21
21
  Description-Content-Type: text/markdown
22
- Requires-Dist: livekit-agents>=0.11
22
+ Requires-Dist: livekit-agents>=0.12.3
23
23
  Requires-Dist: anthropic>=0.34
24
24
 
25
25
  # LiveKit Plugins Anthropic
@@ -0,0 +1,10 @@
1
+ livekit/plugins/anthropic/__init__.py,sha256=1WCyNEaR6qBsX54qJQM0SeY-QHIucww16PLXcSnMqRo,1175
2
+ livekit/plugins/anthropic/llm.py,sha256=e65Z_YchNHCXN2F1kKb8lczfSY1_Ak8Y_94nT12pZGI,18975
3
+ livekit/plugins/anthropic/log.py,sha256=fG1pYSY88AnT738gZrmzF9FO4l4BdGENj3VKHMQB3Yo,72
4
+ livekit/plugins/anthropic/models.py,sha256=wyTr2nl6SL4ylN6s4mHJcqtmgV2mjJysZo89FknWdhI,213
5
+ livekit/plugins/anthropic/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
+ livekit/plugins/anthropic/version.py,sha256=711Prlpzg5p2xCBjcE2dctFtzW_seKcOBI5-dvNUVK4,600
7
+ livekit_plugins_anthropic-0.2.8.dist-info/METADATA,sha256=xG06Y2Xf9RjmmBqJ314_6ZmFlEM0ZCo00K82wJHEHHo,1265
8
+ livekit_plugins_anthropic-0.2.8.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
9
+ livekit_plugins_anthropic-0.2.8.dist-info/top_level.txt,sha256=OoDok3xUmXbZRvOrfvvXB-Juu4DX79dlq188E19YHoo,8
10
+ livekit_plugins_anthropic-0.2.8.dist-info/RECORD,,
@@ -1,10 +0,0 @@
1
- livekit/plugins/anthropic/__init__.py,sha256=1WCyNEaR6qBsX54qJQM0SeY-QHIucww16PLXcSnMqRo,1175
2
- livekit/plugins/anthropic/llm.py,sha256=Qz8POfM4A4Z-MuwcNoD9uJt8lpNi0SvatJvNtqls5p4,20650
3
- livekit/plugins/anthropic/log.py,sha256=fG1pYSY88AnT738gZrmzF9FO4l4BdGENj3VKHMQB3Yo,72
4
- livekit/plugins/anthropic/models.py,sha256=wyTr2nl6SL4ylN6s4mHJcqtmgV2mjJysZo89FknWdhI,213
5
- livekit/plugins/anthropic/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- livekit/plugins/anthropic/version.py,sha256=qiU8NmY5thT_I47ndTlA5TMw4pNi5-r9qqSsLmz-9ps,600
7
- livekit_plugins_anthropic-0.2.6.dist-info/METADATA,sha256=7v72icRCffOPETvp3GbhrJXKRO2yZG7O1eU3OpCeGnM,1263
8
- livekit_plugins_anthropic-0.2.6.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
9
- livekit_plugins_anthropic-0.2.6.dist-info/top_level.txt,sha256=OoDok3xUmXbZRvOrfvvXB-Juu4DX79dlq188E19YHoo,8
10
- livekit_plugins_anthropic-0.2.6.dist-info/RECORD,,