evolution-sdk 0.8.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.
evolution/__init__.py ADDED
@@ -0,0 +1,102 @@
1
+ """
2
+ Evolution Python SDK — AI-Native Version Control Platform.
3
+ "Version Intelligence, Not Code."
4
+ """
5
+
6
+ from pathlib import Path
7
+
8
+ from evolution.adapters import (
9
+ from_anthropic,
10
+ from_crewai,
11
+ from_langchain,
12
+ from_llamaindex,
13
+ from_openai,
14
+ )
15
+ from evolution.capture import RecordContextManager, record, track
16
+ from evolution.evaluators import (
17
+ DimensionScore,
18
+ EvaluationReport,
19
+ SemanticEvaluator,
20
+ )
21
+ from evolution.exceptions import (
22
+ ArtifactNotFoundError,
23
+ CommandExecutionError,
24
+ EvolutionError,
25
+ ManifestNotFoundError,
26
+ ManifestValidationError,
27
+ RepositoryAlreadyExistsError,
28
+ RepositoryNotFoundError,
29
+ )
30
+ from evolution.models import (
31
+ BaseArtifact,
32
+ EvaluationResult,
33
+ EvaluationScore,
34
+ Execution,
35
+ Manifest,
36
+ ManifestArtifacts,
37
+ MemoryArtifact,
38
+ ModelConfigArtifact,
39
+ PolicyArtifact,
40
+ PromptArtifact,
41
+ RetrievalArtifact,
42
+ TokenUsage,
43
+ ToolArtifact,
44
+ artifact_from_dict,
45
+ compute_blob_hash,
46
+ )
47
+ from evolution.repository import CommitInfo, RepoStatus, Repository
48
+
49
+ __version__ = "0.8.0"
50
+
51
+
52
+ def init(path: Path | str = ".", name: str = "ai-intelligence") -> Repository:
53
+ """Convenience function to initialize a new Evolution repository."""
54
+ return Repository.init(path=path, name=name)
55
+
56
+
57
+ def open(path: Path | str = ".") -> Repository:
58
+ """Convenience function to open an existing Evolution repository."""
59
+ return Repository.open(path=path)
60
+
61
+
62
+ __all__ = [
63
+ "ArtifactNotFoundError",
64
+ "BaseArtifact",
65
+ "CommandExecutionError",
66
+ "CommitInfo",
67
+ "DimensionScore",
68
+ "EvaluationReport",
69
+ "EvaluationResult",
70
+ "EvaluationScore",
71
+ "EvolutionError",
72
+ "Execution",
73
+ "Manifest",
74
+ "ManifestArtifacts",
75
+ "ManifestNotFoundError",
76
+ "ManifestValidationError",
77
+ "MemoryArtifact",
78
+ "ModelConfigArtifact",
79
+ "PolicyArtifact",
80
+ "PromptArtifact",
81
+ "RecordContextManager",
82
+ "RepoStatus",
83
+ "Repository",
84
+ "RepositoryAlreadyExistsError",
85
+ "RepositoryNotFoundError",
86
+ "RetrievalArtifact",
87
+ "SemanticEvaluator",
88
+ "TokenUsage",
89
+ "ToolArtifact",
90
+ "__version__",
91
+ "artifact_from_dict",
92
+ "compute_blob_hash",
93
+ "from_anthropic",
94
+ "from_crewai",
95
+ "from_langchain",
96
+ "from_llamaindex",
97
+ "from_openai",
98
+ "init",
99
+ "open",
100
+ "record",
101
+ "track",
102
+ ]
@@ -0,0 +1,28 @@
1
+ """
2
+ Evolution framework adapters package.
3
+ """
4
+
5
+ from evolution.adapters.base import BaseAdapter
6
+ from evolution.adapters.crewai import CrewAIAdapter, from_crewai
7
+ from evolution.adapters.direct import (
8
+ AnthropicAdapter,
9
+ OpenAIAdapter,
10
+ from_anthropic,
11
+ from_openai,
12
+ )
13
+ from evolution.adapters.langchain import LangChainAdapter, from_langchain
14
+ from evolution.adapters.llamaindex import LlamaIndexAdapter, from_llamaindex
15
+
16
+ __all__ = [
17
+ "AnthropicAdapter",
18
+ "BaseAdapter",
19
+ "CrewAIAdapter",
20
+ "LangChainAdapter",
21
+ "LlamaIndexAdapter",
22
+ "OpenAIAdapter",
23
+ "from_anthropic",
24
+ "from_crewai",
25
+ "from_langchain",
26
+ "from_llamaindex",
27
+ "from_openai",
28
+ ]
@@ -0,0 +1,21 @@
1
+ """
2
+ Base protocol and abstract class for framework adapters.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ from abc import ABC, abstractmethod
8
+ from typing import Any
9
+
10
+ from evolution.models.manifest import Manifest
11
+
12
+
13
+ class BaseAdapter(ABC):
14
+ """Abstract base class for converting framework-specific AI configurations
15
+ into standard Intelligence Manifests (Spec v1.0).
16
+ """
17
+
18
+ @abstractmethod
19
+ def to_manifest(self, obj: Any, name: str = "ai-intelligence", description: str = "") -> Manifest:
20
+ """Converts a framework-specific object into an Evolution Manifest."""
21
+ pass
@@ -0,0 +1,86 @@
1
+ """
2
+ CrewAI framework adapter for extracting multi-agent Intelligence Manifests.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ from typing import Any
8
+
9
+ from evolution.adapters.base import BaseAdapter
10
+ from evolution.models.artifacts import (
11
+ ModelConfigArtifact,
12
+ PromptArtifact,
13
+ ToolArtifact,
14
+ )
15
+ from evolution.models.manifest import Manifest
16
+
17
+
18
+ class CrewAIAdapter(BaseAdapter):
19
+ """Converts CrewAI Crews, Agents, and Tasks into a multi-agent Intelligence Manifest."""
20
+
21
+ def to_manifest(self, obj: Any, name: str = "crewai-multi-agent", description: str = "") -> Manifest:
22
+ manifest = Manifest(name=name, description=description or "CrewAI multi-agent system state")
23
+
24
+ agents = getattr(obj, "agents", []) or []
25
+ if not agents and hasattr(obj, "role"): # If a single Agent was passed
26
+ agents = [obj]
27
+
28
+ seen_models = set()
29
+ seen_tools = set()
30
+
31
+ for idx, agent in enumerate(agents):
32
+ role = getattr(agent, "role", f"agent-{idx+1}")
33
+ goal = getattr(agent, "goal", "")
34
+ backstory = getattr(agent, "backstory", "")
35
+
36
+ # 1. Agent role prompt artifact
37
+ prompt_content = f"Role: {role}\nGoal: {goal}\nBackstory: {backstory}".strip()
38
+ manifest.add_artifact(PromptArtifact(
39
+ name=f"{role.lower().replace(' ', '-')}-prompt",
40
+ role="system",
41
+ description=prompt_content[:300],
42
+ ))
43
+
44
+ # 2. Agent tools
45
+ agent_tools = getattr(agent, "tools", []) or []
46
+ for t in agent_tools:
47
+ t_name = getattr(t, "name", str(t))
48
+ if t_name not in seen_tools:
49
+ seen_tools.add(t_name)
50
+ manifest.add_artifact(ToolArtifact(
51
+ name=t_name,
52
+ provider="crewai",
53
+ description=getattr(t, "description", ""),
54
+ ))
55
+
56
+ # 3. Agent LLM
57
+ llm = getattr(agent, "llm", None)
58
+ if llm is not None and str(llm) not in seen_models:
59
+ seen_models.add(str(llm))
60
+ model_str = getattr(llm, "model", getattr(llm, "model_name", str(llm)))
61
+ provider = "openai"
62
+ if "claude" in str(model_str).lower():
63
+ provider = "anthropic"
64
+ elif "gemini" in str(model_str).lower():
65
+ provider = "google"
66
+
67
+ manifest.add_artifact(ModelConfigArtifact(
68
+ name=f"model-{role.lower().replace(' ', '-')}",
69
+ model=str(model_str),
70
+ provider=provider,
71
+ ))
72
+
73
+ # Capture crew structure in metadata
74
+ tasks = getattr(obj, "tasks", []) or []
75
+ manifest.metadata["crewai"] = {
76
+ "agent_count": len(agents),
77
+ "task_count": len(tasks),
78
+ "process": str(getattr(obj, "process", "sequential")),
79
+ }
80
+
81
+ return manifest
82
+
83
+
84
+ def from_crewai(obj: Any, name: str = "crewai-multi-agent", description: str = "") -> Manifest:
85
+ """Convenience function to extract an Intelligence Manifest from a CrewAI Crew or Agent."""
86
+ return CrewAIAdapter().to_manifest(obj, name=name, description=description)
@@ -0,0 +1,120 @@
1
+ """
2
+ Direct API adapters for OpenAI and Anthropic API payloads and clients.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ from typing import Any
8
+
9
+ from evolution.adapters.base import BaseAdapter
10
+ from evolution.models.artifacts import (
11
+ ModelConfigArtifact,
12
+ PromptArtifact,
13
+ ToolArtifact,
14
+ )
15
+ from evolution.models.manifest import Manifest
16
+
17
+
18
+ class OpenAIAdapter(BaseAdapter):
19
+ """Converts OpenAI request dictionaries or client configurations into an Intelligence Manifest."""
20
+
21
+ def to_manifest(self, obj: Any, name: str = "openai-system", description: str = "") -> Manifest:
22
+ manifest = Manifest(name=name, description=description or "OpenAI API intelligence state")
23
+ params = obj if isinstance(obj, dict) else getattr(obj, "__dict__", {})
24
+
25
+ # 1. Model configuration
26
+ model = params.get("model", "gpt-4o")
27
+ temp = params.get("temperature", 0.7)
28
+ max_tokens = params.get("max_tokens") or params.get("max_completion_tokens")
29
+ top_p = params.get("top_p")
30
+
31
+ manifest.add_artifact(ModelConfigArtifact(
32
+ name=f"openai-{model}",
33
+ model=str(model),
34
+ provider="openai",
35
+ temperature=float(temp) if temp is not None else 0.7,
36
+ max_tokens=int(max_tokens) if max_tokens is not None else None,
37
+ top_p=float(top_p) if top_p is not None else None,
38
+ ))
39
+
40
+ # 2. Prompts from messages
41
+ messages = params.get("messages", [])
42
+ for idx, msg in enumerate(messages):
43
+ if isinstance(msg, dict):
44
+ role = msg.get("role", "user")
45
+ content = str(msg.get("content", ""))
46
+ if role in ("system", "user", "assistant", "few_shot"):
47
+ manifest.add_artifact(PromptArtifact(
48
+ name=f"openai-msg-{idx+1}-{role}",
49
+ role=role,
50
+ description=content[:200],
51
+ ))
52
+
53
+ # 3. Tools
54
+ tools = params.get("tools", [])
55
+ for t in tools:
56
+ if isinstance(t, dict):
57
+ fn = t.get("function", {})
58
+ t_name = fn.get("name") or t.get("name", "custom-tool")
59
+ t_desc = fn.get("description", "")
60
+ manifest.add_artifact(ToolArtifact(
61
+ name=t_name,
62
+ provider="openai",
63
+ description=t_desc,
64
+ ))
65
+
66
+ return manifest
67
+
68
+
69
+ class AnthropicAdapter(BaseAdapter):
70
+ """Converts Anthropic request dictionaries or client configurations into an Intelligence Manifest."""
71
+
72
+ def to_manifest(self, obj: Any, name: str = "anthropic-system", description: str = "") -> Manifest:
73
+ manifest = Manifest(name=name, description=description or "Anthropic API intelligence state")
74
+ params = obj if isinstance(obj, dict) else getattr(obj, "__dict__", {})
75
+
76
+ # 1. Model configuration
77
+ model = params.get("model", "claude-3.5-sonnet")
78
+ temp = params.get("temperature", 0.7)
79
+ max_tokens = params.get("max_tokens", 4096)
80
+
81
+ manifest.add_artifact(ModelConfigArtifact(
82
+ name=f"anthropic-{model}",
83
+ model=str(model),
84
+ provider="anthropic",
85
+ temperature=float(temp) if temp is not None else 0.7,
86
+ max_tokens=int(max_tokens) if max_tokens is not None else None,
87
+ ))
88
+
89
+ # 2. System prompt
90
+ system = params.get("system")
91
+ if system:
92
+ manifest.add_artifact(PromptArtifact(
93
+ name="anthropic-system-prompt",
94
+ role="system",
95
+ description=str(system)[:200],
96
+ ))
97
+
98
+ # 3. Tools
99
+ tools = params.get("tools", [])
100
+ for t in tools:
101
+ if isinstance(t, dict):
102
+ t_name = t.get("name", "custom-tool")
103
+ t_desc = t.get("description", "")
104
+ manifest.add_artifact(ToolArtifact(
105
+ name=t_name,
106
+ provider="anthropic",
107
+ description=t_desc,
108
+ ))
109
+
110
+ return manifest
111
+
112
+
113
+ def from_openai(params: dict[str, Any] | Any, name: str = "openai-system", description: str = "") -> Manifest:
114
+ """Convenience function to extract an Intelligence Manifest from an OpenAI request payload."""
115
+ return OpenAIAdapter().to_manifest(params, name=name, description=description)
116
+
117
+
118
+ def from_anthropic(params: dict[str, Any] | Any, name: str = "anthropic-system", description: str = "") -> Manifest:
119
+ """Convenience function to extract an Intelligence Manifest from an Anthropic request payload."""
120
+ return AnthropicAdapter().to_manifest(params, name=name, description=description)
@@ -0,0 +1,112 @@
1
+ """
2
+ LangChain framework adapter for extracting Intelligence Manifests.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ from typing import Any
8
+
9
+ from evolution.adapters.base import BaseAdapter
10
+ from evolution.models.artifacts import (
11
+ MemoryArtifact,
12
+ ModelConfigArtifact,
13
+ PromptArtifact,
14
+ ToolArtifact,
15
+ )
16
+ from evolution.models.manifest import Manifest
17
+
18
+
19
+ class LangChainAdapter(BaseAdapter):
20
+ """Converts LangChain chains, agents, prompt templates, and tools into an Intelligence Manifest."""
21
+
22
+ def to_manifest(self, obj: Any, name: str = "langchain-agent", description: str = "") -> Manifest:
23
+ manifest = Manifest(name=name, description=description or "LangChain application state")
24
+
25
+ # 1. Inspect LLM / Model
26
+ llm = getattr(obj, "llm", None) or getattr(obj, "llm_chain", None)
27
+ if llm is None and (hasattr(obj, "model_name") or hasattr(obj, "model")):
28
+ llm = obj
29
+
30
+ if llm is not None:
31
+ model_name = getattr(llm, "model_name", None) or getattr(llm, "model", "gpt-4o")
32
+ temperature = getattr(llm, "temperature", 0.7)
33
+ max_tokens = getattr(llm, "max_tokens", None) or getattr(llm, "max_output_tokens", None)
34
+
35
+ # Determine provider
36
+ provider = "openai"
37
+ cls_name = llm.__class__.__name__.lower()
38
+ if "anthropic" in cls_name or "claude" in str(model_name).lower():
39
+ provider = "anthropic"
40
+ elif "google" in cls_name or "gemini" in str(model_name).lower():
41
+ provider = "google"
42
+ elif "mistral" in cls_name:
43
+ provider = "mistral"
44
+ elif "cohere" in cls_name:
45
+ provider = "cohere"
46
+
47
+ manifest.add_artifact(ModelConfigArtifact(
48
+ name="langchain-llm",
49
+ model=str(model_name),
50
+ provider=provider,
51
+ temperature=float(temperature) if temperature is not None else 0.7,
52
+ max_tokens=int(max_tokens) if max_tokens is not None else None,
53
+ ))
54
+
55
+ # 2. Inspect Prompts
56
+ prompt = getattr(obj, "prompt", None) or getattr(obj, "prompt_template", None)
57
+ if prompt is None and hasattr(obj, "messages"):
58
+ prompt = obj
59
+
60
+ if prompt is not None:
61
+ prompt_text = ""
62
+ if hasattr(prompt, "template"):
63
+ prompt_text = str(prompt.template)
64
+ elif hasattr(prompt, "messages"):
65
+ msg_strs = []
66
+ for m in prompt.messages:
67
+ role = getattr(m, "role", "system")
68
+ content = getattr(m, "content", getattr(m, "template", str(m)))
69
+ msg_strs.append(f"[{role}] {content}")
70
+ prompt_text = "\n".join(msg_strs)
71
+ else:
72
+ prompt_text = str(prompt)
73
+
74
+ manifest.add_artifact(PromptArtifact(
75
+ name="langchain-prompt",
76
+ role="system",
77
+ description=prompt_text[:200] if prompt_text else "LangChain prompt template",
78
+ ))
79
+
80
+ # 3. Inspect Tools
81
+ tools = getattr(obj, "tools", []) or []
82
+ for t in tools:
83
+ tool_name = getattr(t, "name", str(t))
84
+ tool_desc = getattr(t, "description", "")
85
+ manifest.add_artifact(ToolArtifact(
86
+ name=tool_name,
87
+ provider="langchain",
88
+ description=tool_desc,
89
+ ))
90
+
91
+ # 4. Inspect Memory
92
+ memory = getattr(obj, "memory", None)
93
+ if memory is not None:
94
+ mem_cls = memory.__class__.__name__.lower()
95
+ strategy = "buffer_window"
96
+ if "summary" in mem_cls:
97
+ strategy = "summary"
98
+ elif "vector" in mem_cls:
99
+ strategy = "vector"
100
+
101
+ manifest.add_artifact(MemoryArtifact(
102
+ name="langchain-memory",
103
+ strategy=strategy,
104
+ max_tokens=getattr(memory, "max_token_limit", None),
105
+ ))
106
+
107
+ return manifest
108
+
109
+
110
+ def from_langchain(obj: Any, name: str = "langchain-agent", description: str = "") -> Manifest:
111
+ """Convenience function to extract an Intelligence Manifest from a LangChain object."""
112
+ return LangChainAdapter().to_manifest(obj, name=name, description=description)
@@ -0,0 +1,96 @@
1
+ """
2
+ LlamaIndex framework adapter for extracting Intelligence Manifests.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ from typing import Any
8
+
9
+ from evolution.adapters.base import BaseAdapter
10
+ from evolution.models.artifacts import (
11
+ ModelConfigArtifact,
12
+ RetrievalArtifact,
13
+ )
14
+ from evolution.models.manifest import Manifest
15
+
16
+
17
+ class LlamaIndexAdapter(BaseAdapter):
18
+ """Converts LlamaIndex indices, query engines, and retrievers into an Intelligence Manifest."""
19
+
20
+ def to_manifest(self, obj: Any, name: str = "llamaindex-rag", description: str = "") -> Manifest:
21
+ manifest = Manifest(name=name, description=description or "LlamaIndex RAG application state")
22
+
23
+ # 1. Extract Retrieval settings
24
+ source = "chroma"
25
+ chunk_size: int | None = None
26
+ top_k: int | None = None
27
+
28
+ # Inspect storage_context / vector_store
29
+ sc = getattr(obj, "storage_context", None)
30
+ vs = getattr(sc, "vector_store", None) if sc else getattr(obj, "vector_store", None)
31
+ if vs is not None:
32
+ vs_name = vs.__class__.__name__.lower()
33
+ if "pinecone" in vs_name:
34
+ source = "pinecone"
35
+ elif "weaviate" in vs_name:
36
+ source = "weaviate"
37
+ elif "elasticsearch" in vs_name or "elastic" in vs_name:
38
+ source = "elasticsearch"
39
+ elif "chroma" in vs_name:
40
+ source = "chroma"
41
+ else:
42
+ source = "local"
43
+
44
+ # Inspect retriever / query engine top_k
45
+ retriever = getattr(obj, "retriever", None) or getattr(obj, "_retriever", None)
46
+ if retriever is not None:
47
+ top_k = getattr(retriever, "similarity_top_k", None) or getattr(retriever, "top_k", None)
48
+ elif hasattr(obj, "similarity_top_k"):
49
+ top_k = getattr(obj, "similarity_top_k")
50
+
51
+ # Inspect chunk size
52
+ service_context = getattr(obj, "service_context", None)
53
+ if service_context is not None:
54
+ node_parser = getattr(service_context, "node_parser", None)
55
+ if node_parser is not None:
56
+ chunk_size = getattr(node_parser, "chunk_size", None)
57
+ elif hasattr(obj, "chunk_size"):
58
+ chunk_size = getattr(obj, "chunk_size")
59
+
60
+ manifest.add_artifact(RetrievalArtifact(
61
+ name="llamaindex-retrieval",
62
+ source=source,
63
+ chunk_size=int(chunk_size) if chunk_size is not None else 512,
64
+ top_k=int(top_k) if top_k is not None else 5,
65
+ description="LlamaIndex vector retrieval configuration",
66
+ ))
67
+
68
+ # 2. Extract LLM configuration
69
+ llm = getattr(obj, "llm", None)
70
+ if service_context and not llm:
71
+ llm = getattr(service_context, "llm", None)
72
+
73
+ if llm is not None:
74
+ model_name = getattr(llm, "model", getattr(llm, "model_name", "gpt-4o"))
75
+ temperature = getattr(llm, "temperature", 0.1)
76
+
77
+ provider = "openai"
78
+ cls_name = llm.__class__.__name__.lower()
79
+ if "anthropic" in cls_name or "claude" in str(model_name).lower():
80
+ provider = "anthropic"
81
+ elif "google" in cls_name or "gemini" in str(model_name).lower():
82
+ provider = "google"
83
+
84
+ manifest.add_artifact(ModelConfigArtifact(
85
+ name="llamaindex-llm",
86
+ model=str(model_name),
87
+ provider=provider,
88
+ temperature=float(temperature) if temperature is not None else 0.1,
89
+ ))
90
+
91
+ return manifest
92
+
93
+
94
+ def from_llamaindex(obj: Any, name: str = "llamaindex-rag", description: str = "") -> Manifest:
95
+ """Convenience function to extract an Intelligence Manifest from a LlamaIndex object."""
96
+ return LlamaIndexAdapter().to_manifest(obj, name=name, description=description)
@@ -0,0 +1,22 @@
1
+ """
2
+ Automatic intelligence capture and execution recording package.
3
+ """
4
+
5
+ from evolution.capture.introspect import (
6
+ extract_docstring_prompt,
7
+ extract_inputs_from_args,
8
+ extract_llm_response,
9
+ extract_model_config_from_kwargs,
10
+ )
11
+ from evolution.capture.recorder import RecordContextManager, record
12
+ from evolution.capture.tracker import track
13
+
14
+ __all__ = [
15
+ "RecordContextManager",
16
+ "extract_docstring_prompt",
17
+ "extract_inputs_from_args",
18
+ "extract_llm_response",
19
+ "extract_model_config_from_kwargs",
20
+ "record",
21
+ "track",
22
+ ]