Initial SQL-only 1C adapter baseline
This commit is contained in:
@@ -0,0 +1,258 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Return a compact agent starting context for a 1C metadata object."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import base64
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
||||
from get_1c_form_context import collect_forms, merge_effective as merge_effective_forms # noqa: E402
|
||||
from get_1c_object_code_context import ( # noqa: E402
|
||||
collect_modules,
|
||||
extension_name_from_path,
|
||||
merge_effective as merge_effective_modules,
|
||||
)
|
||||
from get_1c_object_metadata import build_object_metadata # noqa: E402
|
||||
from resolve_1c_object import load_json, resolve_object # noqa: E402
|
||||
|
||||
|
||||
def decode_arg(value: str | None, encoded: str | None) -> str | None:
|
||||
if encoded:
|
||||
return base64.b64decode(encoded).decode("utf-8")
|
||||
return value
|
||||
|
||||
|
||||
def module_summary(module: dict[str, Any]) -> dict[str, Any]:
|
||||
overlays = module.get("extension_overlays") or []
|
||||
return {
|
||||
"name": module.get("name"),
|
||||
"kind": module.get("kind"),
|
||||
"origin": module.get("origin"),
|
||||
"effective_action": module.get("effective_action"),
|
||||
"size": module.get("size"),
|
||||
"relative_path": module.get("relative_path"),
|
||||
"overlay_count": len(overlays),
|
||||
"overlays": [
|
||||
{
|
||||
"extension": (overlay.get("origin") or {}).get("extension"),
|
||||
"effective_action": overlay.get("effective_action"),
|
||||
"size": overlay.get("size"),
|
||||
"relative_path": overlay.get("relative_path"),
|
||||
}
|
||||
for overlay in overlays
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def form_summary(form: dict[str, Any]) -> dict[str, Any]:
|
||||
overlays = form.get("extension_overlays") or []
|
||||
return {
|
||||
"name": form.get("name"),
|
||||
"synonym": form.get("synonym"),
|
||||
"uuid": form.get("uuid"),
|
||||
"origin": form.get("origin"),
|
||||
"effective_action": form.get("effective_action"),
|
||||
"meta_xml_path": form.get("meta_xml_path"),
|
||||
"form_xml_path": form.get("form_xml_path"),
|
||||
"module_path": form.get("module_path"),
|
||||
"overlay_count": len(overlays),
|
||||
"overlays": [
|
||||
{
|
||||
"extension": (overlay.get("origin") or {}).get("extension"),
|
||||
"effective_action": overlay.get("effective_action"),
|
||||
"uuid": overlay.get("uuid"),
|
||||
"form_xml_path": overlay.get("form_xml_path"),
|
||||
"module_path": overlay.get("module_path"),
|
||||
}
|
||||
for overlay in overlays
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def attribute_summary(attribute: dict[str, Any]) -> dict[str, Any]:
|
||||
result = {
|
||||
"name": attribute.get("name"),
|
||||
"synonym": attribute.get("synonym"),
|
||||
"type": attribute.get("type"),
|
||||
"types": attribute.get("types") or [],
|
||||
"origin": attribute.get("origin"),
|
||||
"effective_action": attribute.get("effective_action"),
|
||||
}
|
||||
if attribute.get("is_composite"):
|
||||
result["is_composite"] = True
|
||||
return {key: value for key, value in result.items() if value not in (None, [], "")}
|
||||
|
||||
|
||||
def extension_names_from_resolution(resolution: dict[str, Any]) -> list[str]:
|
||||
names = []
|
||||
for overlay in resolution.get("extension_overlays") or []:
|
||||
name = extension_name_from_path(overlay.get("path")) or overlay.get("extension_name")
|
||||
if name and name not in names:
|
||||
names.append(name)
|
||||
return names
|
||||
|
||||
|
||||
def view_modules(canonical: dict[str, Any], resolution: dict[str, Any], *, view: str, extension: str | None) -> tuple[list[dict[str, Any]], dict[str, int]]:
|
||||
base_modules = collect_modules(canonical.get("path"), source="base")
|
||||
extension_modules = []
|
||||
for overlay in resolution.get("extension_overlays") or []:
|
||||
overlay_extension = extension_name_from_path(overlay.get("path")) or overlay.get("extension_name")
|
||||
extension_modules.extend(collect_modules(overlay.get("path"), source="extension", extension_name=overlay_extension))
|
||||
if view == "base":
|
||||
modules = [{**item, "effective_action": "base"} for item in base_modules]
|
||||
elif view == "extension":
|
||||
if not extension:
|
||||
raise SystemExit("Use --extension with --view extension.")
|
||||
modules = [
|
||||
{**item, "effective_action": "extended_or_added"}
|
||||
for item in extension_modules
|
||||
if (item.get("origin") or {}).get("extension") == extension
|
||||
]
|
||||
else:
|
||||
modules = merge_effective_modules(base_modules, extension_modules)
|
||||
return modules, {"modules": len(modules), "base_modules": len(base_modules), "extension_modules": len(extension_modules)}
|
||||
|
||||
|
||||
def view_forms(canonical: dict[str, Any], resolution: dict[str, Any], *, view: str, extension: str | None) -> tuple[list[dict[str, Any]], dict[str, int]]:
|
||||
base_forms = collect_forms(canonical.get("path"), source="base")
|
||||
extension_forms = []
|
||||
for overlay in resolution.get("extension_overlays") or []:
|
||||
overlay_extension = extension_name_from_path(overlay.get("path")) or overlay.get("extension_name")
|
||||
extension_forms.extend(collect_forms(overlay.get("path"), source="extension", extension_name=overlay_extension))
|
||||
if view == "base":
|
||||
forms = [{**item, "effective_action": "base"} for item in base_forms]
|
||||
elif view == "extension":
|
||||
if not extension:
|
||||
raise SystemExit("Use --extension with --view extension.")
|
||||
forms = [
|
||||
{**item, "effective_action": "extended_or_added"}
|
||||
for item in extension_forms
|
||||
if (item.get("origin") or {}).get("extension") == extension
|
||||
]
|
||||
else:
|
||||
forms = merge_effective_forms(base_forms, extension_forms)
|
||||
return forms, {"forms": len(forms), "base_forms": len(base_forms), "extension_forms": len(extension_forms)}
|
||||
|
||||
|
||||
def build_brief_context(
|
||||
index: dict[str, Any],
|
||||
*,
|
||||
kind: str,
|
||||
name: str,
|
||||
view: str,
|
||||
extension: str | None,
|
||||
max_attributes: int,
|
||||
max_modules: int,
|
||||
max_forms: int,
|
||||
) -> dict[str, Any]:
|
||||
resolution = resolve_object(index, kind=kind, name=name, limit=100)
|
||||
canonical = resolution.get("canonical")
|
||||
if not canonical:
|
||||
raise SystemExit(f"Object not found: {kind}.{name}")
|
||||
|
||||
metadata = build_object_metadata(index, kind=kind, name=name, view=view, extension=extension, include_storage=False)
|
||||
modules, module_counts = view_modules(canonical, resolution, view=view, extension=extension)
|
||||
forms, form_counts = view_forms(canonical, resolution, view=view, extension=extension)
|
||||
|
||||
attributes = metadata.get("attributes") or []
|
||||
tabular_sections = metadata.get("tabular_sections") or []
|
||||
extension_names = extension_names_from_resolution(resolution)
|
||||
return {
|
||||
"schema": "onec_object_brief_context.v1",
|
||||
"view": view,
|
||||
"extension": extension if view == "extension" else None,
|
||||
"object": metadata.get("object"),
|
||||
"active_extensions": extension_names,
|
||||
"attributes": {
|
||||
"items": [attribute_summary(item) for item in attributes[:max_attributes]],
|
||||
"total": len(attributes),
|
||||
"truncated": len(attributes) > max_attributes,
|
||||
},
|
||||
"tabular_sections": {
|
||||
"items": [
|
||||
{
|
||||
"name": item.get("name"),
|
||||
"synonym": item.get("synonym"),
|
||||
"origin": item.get("origin"),
|
||||
}
|
||||
for item in tabular_sections
|
||||
],
|
||||
"total": len(tabular_sections),
|
||||
},
|
||||
"forms": {
|
||||
"items": [form_summary(item) for item in forms[:max_forms]],
|
||||
"counts": form_counts,
|
||||
"truncated": len(forms) > max_forms,
|
||||
},
|
||||
"modules": {
|
||||
"items": [module_summary(item) for item in modules[:max_modules]],
|
||||
"counts": module_counts,
|
||||
"truncated": len(modules) > max_modules,
|
||||
},
|
||||
"next_tools": {
|
||||
"metadata": "python scripts/get_1c_object_metadata.py --kind <Kind> --name <Name> --view effective",
|
||||
"read_data": "python scripts/read_1c_object_view.py --kind <Kind> --name <Name> --view effective",
|
||||
"form": "python scripts/get_1c_form_context.py --kind <Kind> --name <Name> --form <FormName> --view effective",
|
||||
"code_context": "python scripts/get_1c_object_code_context.py --kind <Kind> --name <Name> --view effective",
|
||||
"module": "python scripts/get_1c_module.py --kind <Kind> --name <Name> --module <ModuleName> --view effective",
|
||||
},
|
||||
"counts": {
|
||||
"attributes": len(attributes),
|
||||
"tabular_sections": len(tabular_sections),
|
||||
**form_counts,
|
||||
**module_counts,
|
||||
},
|
||||
"resolution": {
|
||||
"schema": resolution.get("schema"),
|
||||
"canonical": canonical,
|
||||
"summary": resolution.get("summary"),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(description="Get compact 1C object context for agents.")
|
||||
parser.add_argument("--index", type=Path, required=True)
|
||||
parser.add_argument("--kind")
|
||||
parser.add_argument("--name")
|
||||
parser.add_argument("--kind-b64")
|
||||
parser.add_argument("--name-b64")
|
||||
parser.add_argument("--view", choices=["effective", "base", "extension"], default="effective")
|
||||
parser.add_argument("--extension")
|
||||
parser.add_argument("--max-attributes", type=int, default=40)
|
||||
parser.add_argument("--max-modules", type=int, default=30)
|
||||
parser.add_argument("--max-forms", type=int, default=20)
|
||||
parser.add_argument("--output", type=Path)
|
||||
args = parser.parse_args()
|
||||
|
||||
kind = decode_arg(args.kind, args.kind_b64)
|
||||
name = decode_arg(args.name, args.name_b64)
|
||||
if not kind or not name:
|
||||
raise SystemExit("Use --kind/--name or --kind-b64/--name-b64.")
|
||||
result = build_brief_context(
|
||||
load_json(args.index),
|
||||
kind=kind,
|
||||
name=name,
|
||||
view=args.view,
|
||||
extension=args.extension,
|
||||
max_attributes=args.max_attributes,
|
||||
max_modules=args.max_modules,
|
||||
max_forms=args.max_forms,
|
||||
)
|
||||
text = json.dumps(result, ensure_ascii=False, indent=2) + "\n"
|
||||
if args.output:
|
||||
args.output.parent.mkdir(parents=True, exist_ok=True)
|
||||
args.output.write_text(text, encoding="utf-8")
|
||||
print(json.dumps({"output": str(args.output), "counts": result["counts"], "view": result["view"]}, ensure_ascii=False))
|
||||
else:
|
||||
print(text)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user