Fix Codex package local source references
This commit is contained in:
@@ -162,8 +162,9 @@ def _write_codex_package(
|
|||||||
_write_json(root / "indexes" / "source-map.json", {"files": source_map})
|
_write_json(root / "indexes" / "source-map.json", {"files": source_map})
|
||||||
if snapshot is not None:
|
if snapshot is not None:
|
||||||
(root / "raw" / "sir_snapshot.json").write_bytes(snapshot_to_json(snapshot))
|
(root / "raw" / "sir_snapshot.json").write_bytes(snapshot_to_json(snapshot))
|
||||||
objects = _ai_objects(snapshot)
|
source_lookup = _source_lookup(source_map)
|
||||||
modules = _ai_modules(snapshot)
|
objects = _ai_objects(snapshot, source_lookup)
|
||||||
|
modules = _ai_modules(snapshot, source_lookup)
|
||||||
_write_json(root / "indexes" / "objects.json", objects)
|
_write_json(root / "indexes" / "objects.json", objects)
|
||||||
_write_json(root / "indexes" / "modules.json", modules)
|
_write_json(root / "indexes" / "modules.json", modules)
|
||||||
_write_json(root / "indexes" / "edges.json", [edge.model_dump(mode="json") for edge in snapshot.edges])
|
_write_json(root / "indexes" / "edges.json", [edge.model_dump(mode="json") for edge in snapshot.edges])
|
||||||
@@ -215,6 +216,24 @@ def _copy_codex_sources(input_path: Path, target: Path) -> list[dict[str, Any]]:
|
|||||||
return copied
|
return copied
|
||||||
|
|
||||||
|
|
||||||
|
def _source_lookup(source_map: list[dict[str, Any]]) -> dict[str, str]:
|
||||||
|
lookup: dict[str, str] = {}
|
||||||
|
for item in source_map:
|
||||||
|
if not item.get("copied"):
|
||||||
|
continue
|
||||||
|
codex_path = str(item.get("codex_path") or "")
|
||||||
|
if not codex_path:
|
||||||
|
continue
|
||||||
|
for key in ["relative_path", "original_path"]:
|
||||||
|
value = str(item.get(key) or "")
|
||||||
|
if not value:
|
||||||
|
continue
|
||||||
|
normalized = value.replace("\\", "/")
|
||||||
|
lookup[normalized] = codex_path
|
||||||
|
lookup[str(Path(value)).replace("\\", "/")] = codex_path
|
||||||
|
return lookup
|
||||||
|
|
||||||
|
|
||||||
def _codex_agents_markdown(manifest: dict[str, Any]) -> str:
|
def _codex_agents_markdown(manifest: dict[str, Any]) -> str:
|
||||||
return f"""# AGENTS.md for 1C context package
|
return f"""# AGENTS.md for 1C context package
|
||||||
|
|
||||||
@@ -371,6 +390,9 @@ def _module_markdown(item: dict[str, Any]) -> str:
|
|||||||
|
|
||||||
|
|
||||||
def _local_source_path(item: dict[str, Any]) -> str:
|
def _local_source_path(item: dict[str, Any]) -> str:
|
||||||
|
local = str(item.get("local_source_path") or "")
|
||||||
|
if local:
|
||||||
|
return local
|
||||||
source = item.get("source") or {}
|
source = item.get("source") or {}
|
||||||
if not isinstance(source, dict):
|
if not isinstance(source, dict):
|
||||||
return ""
|
return ""
|
||||||
@@ -378,6 +400,16 @@ def _local_source_path(item: dict[str, Any]) -> str:
|
|||||||
return f"source/{source_path}" if source_path else ""
|
return f"source/{source_path}" if source_path else ""
|
||||||
|
|
||||||
|
|
||||||
|
def _source_ref_local_path(source_ref: object | None, source_lookup: dict[str, str]) -> str:
|
||||||
|
if source_ref is None:
|
||||||
|
return ""
|
||||||
|
source_path = str(getattr(source_ref, "source_path", "") or "")
|
||||||
|
if not source_path:
|
||||||
|
return ""
|
||||||
|
normalized = source_path.replace("\\", "/")
|
||||||
|
return source_lookup.get(normalized) or source_lookup.get(str(Path(source_path)).replace("\\", "/")) or ""
|
||||||
|
|
||||||
|
|
||||||
def _normalized_tree_markdown(normalized: NormalizedProject) -> str:
|
def _normalized_tree_markdown(normalized: NormalizedProject) -> str:
|
||||||
lines = [f"# Metadata Tree: {normalized.project_id or 'project'}", ""]
|
lines = [f"# Metadata Tree: {normalized.project_id or 'project'}", ""]
|
||||||
for group in normalized.configuration.groups:
|
for group in normalized.configuration.groups:
|
||||||
@@ -395,7 +427,7 @@ def _normalized_tree_markdown(normalized: NormalizedProject) -> str:
|
|||||||
return "\n".join(lines)
|
return "\n".join(lines)
|
||||||
|
|
||||||
|
|
||||||
def _ai_objects(snapshot: SirSnapshot) -> list[dict[str, Any]]:
|
def _ai_objects(snapshot: SirSnapshot, source_lookup: dict[str, str] | None = None) -> list[dict[str, Any]]:
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
"kind": node.kind.value if hasattr(node.kind, "value") else str(node.kind),
|
"kind": node.kind.value if hasattr(node.kind, "value") else str(node.kind),
|
||||||
@@ -404,6 +436,7 @@ def _ai_objects(snapshot: SirSnapshot) -> list[dict[str, Any]]:
|
|||||||
"lineage_id": node.lineage_id,
|
"lineage_id": node.lineage_id,
|
||||||
"semantic_id": node.semantic_id,
|
"semantic_id": node.semantic_id,
|
||||||
"source": None if node.source_ref is None else node.source_ref.model_dump(mode="json"),
|
"source": None if node.source_ref is None else node.source_ref.model_dump(mode="json"),
|
||||||
|
"local_source_path": _source_ref_local_path(node.source_ref, source_lookup or {}),
|
||||||
"attributes": node.attributes,
|
"attributes": node.attributes,
|
||||||
}
|
}
|
||||||
for node in snapshot.nodes
|
for node in snapshot.nodes
|
||||||
@@ -411,13 +444,14 @@ def _ai_objects(snapshot: SirSnapshot) -> list[dict[str, Any]]:
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def _ai_modules(snapshot: SirSnapshot) -> list[dict[str, Any]]:
|
def _ai_modules(snapshot: SirSnapshot, source_lookup: dict[str, str] | None = None) -> list[dict[str, Any]]:
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
"name": node.name,
|
"name": node.name,
|
||||||
"qualified_name": node.qualified_name,
|
"qualified_name": node.qualified_name,
|
||||||
"lineage_id": node.lineage_id,
|
"lineage_id": node.lineage_id,
|
||||||
"source": None if node.source_ref is None else node.source_ref.model_dump(mode="json"),
|
"source": None if node.source_ref is None else node.source_ref.model_dump(mode="json"),
|
||||||
|
"local_source_path": _source_ref_local_path(node.source_ref, source_lookup or {}),
|
||||||
"attributes": node.attributes,
|
"attributes": node.attributes,
|
||||||
}
|
}
|
||||||
for node in snapshot.nodes
|
for node in snapshot.nodes
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
import json
|
||||||
import re
|
import re
|
||||||
import time
|
import time
|
||||||
from types import SimpleNamespace
|
from types import SimpleNamespace
|
||||||
@@ -1716,6 +1717,10 @@ def test_ai_structure_prepare_writes_ai_ready_package(tmp_path: Path):
|
|||||||
assert (codex_package / "raw" / "normalized_project.json").exists()
|
assert (codex_package / "raw" / "normalized_project.json").exists()
|
||||||
assert (codex_package / "source" / "metadata.xml").exists()
|
assert (codex_package / "source" / "metadata.xml").exists()
|
||||||
assert (codex_package / "source" / "Интеграция.bsl").read_text(encoding="utf-8").startswith("Процедура")
|
assert (codex_package / "source" / "Интеграция.bsl").read_text(encoding="utf-8").startswith("Процедура")
|
||||||
|
modules_index = json.loads((codex_package / "indexes" / "modules.json").read_text(encoding="utf-8"))
|
||||||
|
assert any(item.get("local_source_path") == "source/Интеграция.bsl" for item in modules_index)
|
||||||
|
module_docs = "\n".join(path.read_text(encoding="utf-8") for path in (codex_package / "modules").glob("*.md"))
|
||||||
|
assert "Local source: `source/Интеграция.bsl`" in module_docs
|
||||||
assert "generated by SFERA for Codex" in (codex_package / "AGENTS.md").read_text(encoding="utf-8")
|
assert "generated by SFERA for Codex" in (codex_package / "AGENTS.md").read_text(encoding="utf-8")
|
||||||
assert "Use `source/`" in (codex_package / "AGENTS.md").read_text(encoding="utf-8")
|
assert "Use `source/`" in (codex_package / "AGENTS.md").read_text(encoding="utf-8")
|
||||||
assert "Copy this whole folder into the Codex project" in (codex_package / "README.md").read_text(encoding="utf-8")
|
assert "Copy this whole folder into the Codex project" in (codex_package / "README.md").read_text(encoding="utf-8")
|
||||||
|
|||||||
Reference in New Issue
Block a user