feat: add emulated tool-calling bridge for Lingma
Add a proxy-side tool emulation layer so Lingma requests can surface stable OpenAI tool_calls and Anthropic tool_use blocks even when upstream tool events are missing or inconsistent. Constraint: Keep native Lingma tool event bridging as the first path and layer emulation as a fallback Rejected: Depend exclusively on Lingma native tool/invoke events | tool visibility remains inconsistent across models and transports Confidence: high Scope-risk: moderate
This commit is contained in:
@@ -3,6 +3,7 @@ from __future__ import annotations
|
||||
import io
|
||||
import json
|
||||
import os
|
||||
import shutil
|
||||
import time
|
||||
import urllib.request
|
||||
import zipfile
|
||||
@@ -70,6 +71,15 @@ def _extract_release_tree(
|
||||
dst.write(src.read())
|
||||
|
||||
|
||||
def _release_dir_for_binary(lingma_bin: Path, release_root: str | None) -> Path:
|
||||
return lingma_bin.parent / ((release_root or "").strip() or "2.5.20")
|
||||
|
||||
|
||||
def _release_has_required_assets(release_dir: Path) -> bool:
|
||||
extension_main = release_dir / "extension" / "main.js"
|
||||
return extension_main.exists() and extension_main.is_file()
|
||||
|
||||
|
||||
def _query_marketplace_latest_vsix(
|
||||
publisher: str, extension: str
|
||||
) -> tuple[str, str, dict]:
|
||||
@@ -168,8 +178,19 @@ def bootstrap_from_vsix() -> None:
|
||||
)
|
||||
resolved_url = vsix_url
|
||||
|
||||
current_release_dir = _release_dir_for_binary(
|
||||
lingma_bin, old_marker.get("release_root") if isinstance(old_marker, dict) else None
|
||||
)
|
||||
release_ready = _release_has_required_assets(current_release_dir)
|
||||
if lingma_bin.exists() and not release_ready:
|
||||
print(
|
||||
"[bootstrap] existing Lingma binary found but extension assets are incomplete; "
|
||||
f"refreshing install under {current_release_dir}"
|
||||
)
|
||||
|
||||
if (
|
||||
lingma_bin.exists()
|
||||
and release_ready
|
||||
and not force_refresh
|
||||
and (
|
||||
(not always_refresh)
|
||||
@@ -215,7 +236,8 @@ def bootstrap_from_vsix() -> None:
|
||||
lingma_bytes = inner_zip.read(lingma_member)
|
||||
release_root = _infer_release_root(lingma_member)
|
||||
lingma_bin.parent.mkdir(parents=True, exist_ok=True)
|
||||
release_dir = lingma_bin.parent / (release_root or "2.5.20")
|
||||
release_dir = _release_dir_for_binary(lingma_bin, release_root)
|
||||
shutil.rmtree(release_dir, ignore_errors=True)
|
||||
_extract_release_tree(inner_zip, release_root, release_dir)
|
||||
|
||||
lingma_bin.write_bytes(lingma_bytes)
|
||||
@@ -224,7 +246,9 @@ def bootstrap_from_vsix() -> None:
|
||||
if extension_main.exists():
|
||||
print(f"[bootstrap] extension ready: {extension_main}")
|
||||
else:
|
||||
print(f"[bootstrap] extension missing under: {release_dir}")
|
||||
raise RuntimeError(
|
||||
f"extension assets missing after extraction under: {release_dir}"
|
||||
)
|
||||
|
||||
marker = {
|
||||
"source": source_type,
|
||||
|
||||
Reference in New Issue
Block a user